Android自定義View實(shí)現(xiàn)簡(jiǎn)易畫板功能
本文實(shí)例為大家分享了Android自定義View實(shí)現(xiàn)簡(jiǎn)易畫板的具體代碼,供大家參考,具體內(nèi)容如下
自定義VIew實(shí)現(xiàn)簡(jiǎn)易畫板效果,功能包括清空、選擇顏色,選擇大小,效果如下
畫板布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ? ? xmlns:tools="http://schemas.android.com/tools" ? ? android:layout_width="match_parent" ? ? android:layout_height="match_parent" ? ? android:gravity="center" ? ? android:orientation="vertical" ? ? tools:context=".MainActivity"> ? ? <!-- 這是一個(gè)自定義組合控件,包含涂鴉板及右邊三個(gè)按鈕 --> ? ? <com.android.mytest.GraffitiBroadLayout ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="match_parent" /> </LinearLayout>
自定義view GraffitiBroadLayout 布局文件 view_graffiti.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" ? ? android:layout_width="match_parent" ? ? android:layout_height="match_parent" ? ? android:orientation="horizontal" ? ? android:baselineAligned="false"> ? ? <!-- 自定義涂鴉板View --> ? ? <com.android.mytest.GraffitiView ? ? ? ? android:id="@+id/graffiti_view" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="match_parent" ? ? ? ? android:orientation="horizontal" /> ? ? <androidx.recyclerview.widget.RecyclerView ? ? ? ? android:id="@+id/recycler_view" ? ? ? ? android:visibility="gone" ? ? ? ? android:layout_gravity="right" ? ? ? ? android:layout_marginRight="100dp" ? ? ? ? android:layout_width="80dp" ? ? ? ? android:layout_height="wrap_content"/> ? ? <!-- 右側(cè)三個(gè)按鈕 清空、顏色、粗細(xì) --> ? ? <LinearLayout ? ? ? ? android:layout_gravity="right" ? ? ? ? android:orientation="vertical" ? ? ? ? android:layout_width="100dp" ? ? ? ? android:layout_height="match_parent"> ? ? ? ? <Button ? ? ? ? ? ? android:id="@+id/clear_all" ? ? ? ? ? ? android:layout_width="match_parent" ? ? ? ? ? ? android:layout_height="wrap_content"/> ? ? ? ? <Button ? ? ? ? ? ? android:id="@+id/select_color" ? ? ? ? ? ? android:layout_width="match_parent" ? ? ? ? ? ? android:layout_height="wrap_content"/> ? ? ? ? <Button ? ? ? ? ? ? android:id="@+id/select_size" ? ? ? ? ? ? android:layout_width="match_parent" ? ? ? ? ? ? android:layout_height="wrap_content"/> ? ? </LinearLayout> </FrameLayout>
畫板布局中包括一個(gè) 自定義涂鴉view,recyclerView用于顯示選擇顏色、大小,三個(gè)按鈕,分別是:
清空、選擇顏色、選擇大小
// 繼承LinearLayout? public class GraffitiBroadLayout extends LinearLayout { ?? ? ? ? private final int[] colors = {R.color.red,R.color.green,R.color.blue};// 顏色數(shù)組 ? ? private final int[] sizes = {5,10,15,20};// 畫筆size數(shù)組 ? ? private Context mContext; ? ? private View mView; ? ? private GraffitiView mGraffitiView; ? ? private RecyclerView mRecyclerView; ? ? public GraffitiBroadLayout(Context context) { ? ? ? ? super(context); ? ? } ? ? public GraffitiBroadLayout(Context context, @Nullable AttributeSet attrs) { ? ? ? ? super(context, attrs); ? ? ? ? mContext = context; ? ? ? ? // 獲取布局View ? ? ? ? mView = LayoutInflater.from(context).inflate(R.layout.view_graffiti, this,true); ? ? ? ? initView();// 初始化并設(shè)置點(diǎn)擊事件 ? ? } ? ? private void initView() { ? ? ? ? Button clearAllBtn = mView.findViewById(R.id.clear_all); ? ? ? ? Button selectColorBtn = mView.findViewById(R.id.select_color); ? ? ? ? Button selectSizeBtn = mView.findViewById(R.id.select_size); ? ? ? ? mGraffitiView = mView.findViewById(R.id.graffiti_view); ? ? ? ? mRecyclerView = mView.findViewById(R.id.recycler_view); ? ? ? ? mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); ? ? ? ? // 點(diǎn)擊清空 畫板 ? ? ? ? clearAllBtn.setOnClickListener(v -> mGraffitiView.clearAllPath()); ? ? ? ? // 選擇畫筆顏色 ? ? ? ? selectColorBtn.setOnClickListener(v -> { ? ? ? ? ? ? GraffitiAdapter adapter = new GraffitiAdapter(mContext,colors,1); ? ? ? ? ? ? mRecyclerView.setAdapter(adapter); ? ? ? ? ? ? mRecyclerView.setVisibility(VISIBLE); ? ? ? ? }); ? ? ? ? // 選擇畫筆大小 ? ? ? ? selectSizeBtn.setOnClickListener(v -> { ? ? ? ? ? ? GraffitiAdapter adapter = new GraffitiAdapter(mContext,sizes,2); ? ? ? ? ? ? mRecyclerView.setAdapter(adapter); ? ? ? ? ? ? mRecyclerView.setVisibility(VISIBLE); ? ? ? ? }); ? ? } ?? ?// 自定義adapter ? ? class GraffitiAdapter extends RecyclerView.Adapter<GraffitiViewHolder>{ ? ? ? ? Context mContext; ? ? ? ? int[] cs; ? ? ? ? int type;// 用于判斷顯示顏色 還是 選擇大小 ? ? ? ? public GraffitiAdapter(Context mContext, int[] cs,int type) { ? ? ? ? ? ? this.mContext = mContext; ? ? ? ? ? ? this.cs = cs; ? ? ? ? ? ? this.type = type; ? ? ? ? } ? ? ? ? @NonNull ? ? ? ? @Override ? ? ? ? public GraffitiViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { ? ? ? ? ? ? // 獲取 item 布局 ? ? ? ? ? ? View view = LayoutInflater.from(mContext).inflate(R.layout.item_recycler_graffiti,parent,false); ? ? ? ? ? ? return new GraffitiViewHolder(view); ? ? ? ? } ? ? ? ? @Override ? ? ? ? public void onBindViewHolder(@NonNull GraffitiViewHolder holder, int position) { ? ? ? ? ? ? if(type == 1){// 顏色 ? ? ? ? ? ? ? ? holder.view.setBackgroundResource(cs[position]); ? ? ? ? ? ? ? ? holder.click.setOnClickListener(v -> { ? ? ? ? ? ? ? ? ?? ?// 設(shè)置畫筆顏色 ? ? ? ? ? ? ? ? ? ? mGraffitiView.setPaintColor(cs[position]); ? ? ? ? ? ? ? ? ? ? mRecyclerView.setVisibility(GONE); ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? }else if(type == 2){// size ? ? ? ? ? ? ? ? ViewGroup.LayoutParams lp = holder.view.getLayoutParams(); ? ? ? ? ? ? ? ? lp.height = sizes[position]*2; ? ? ? ? ? ? ? ? holder.view.setLayoutParams(lp); ? ? ? ? ? ? ? ? holder.view.setBackgroundResource(R.color.black); ? ? ? ? ? ? ? ? holder.click.setOnClickListener(v -> { ? ? ? ? ? ? ? ? ?? ?// 設(shè)置畫筆size ? ? ? ? ? ? ? ? ? ? mGraffitiView.setPaintSize(sizes[position]); ? ? ? ? ? ? ? ? ? ? mRecyclerView.setVisibility(GONE); ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? @Override ? ? ? ? public int getItemCount() { ? ? ? ? ? ? return cs.length; ? ? ? ? } ? ? } ? ? static class GraffitiViewHolder extends RecyclerView.ViewHolder{ ? ? ? ? View view; ? ? ? ? LinearLayout click; ? ? ? ? public GraffitiViewHolder(@NonNull View itemView) { ? ? ? ? ? ? super(itemView); ? ? ? ? ? ? view = itemView.findViewById(R.id.item_view); ? ? ? ? ? ? click = itemView.findViewById(R.id.click_view); ? ? ? ? } ? ? } }
item_recycler_graffiti.xml 布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ? ? xmlns:tools="http://schemas.android.com/tools" ? ? android:layout_width="match_parent" ? ? android:layout_marginTop="10dp" ? ? android:layout_height="50dp" ? ? android:gravity="center"> ? ? <LinearLayout ? ? ? ? android:id="@+id/click_view" ? ? ? ? android:gravity="center" ? ? ? ? android:layout_width="match_parent" ? ? ? ? android:layout_height="match_parent" ? ? ? ? tools:ignore="UselessParent"> ? ? ? ? <View ? ? ? ? ? ? android:id="@+id/item_view" ? ? ? ? ? ? android:layout_width="match_parent" ? ? ? ? ? ? android:layout_height="40dp"/> ? ? </LinearLayout> </LinearLayout>
自定義涂鴉View:
public class GraffitiView extends View { ? ? private final Context mContext; ? ? private Canvas mCanvas;//? ? ? private Bitmap mBitmap;// 用于保存繪制過的路徑的 bitmap ? ? private Paint mPaint;// 畫筆 ? ? private Path mPath;// 觸摸時(shí)的路徑 ? ? private int width,height; ? ? public GraffitiView(Context context) { ? ? ? ? this(context,null); ? ? } ? ? public GraffitiView(Context context, @Nullable AttributeSet attrs) { ? ? ? ? super(context, attrs); ? ? ? ? mContext = context; ? ? ? ? init(); ? ? } ? ? private void init() { ? ? ?? ?// 初始化 畫筆 ? ? ? ? mPaint = new Paint(); ? ? ? ? mPaint.setColor(mContext.getColor(R.color.green));//畫筆顏色 ? ? ? ? mPaint.setAntiAlias(true);// 抗鋸齒 ? ? ? ? mPaint.setDither(true);// 抖動(dòng)處理 ? ? ? ? mPaint.setStrokeJoin(Paint.Join.ROUND);//畫筆連接處 圓弧 ? ? ? ? mPaint.setStrokeCap(Paint.Cap.ROUND);//畫筆拐彎處風(fēng)格 圓弧 ? ? ? ? mPaint.setStyle(Paint.Style.STROKE);//畫筆格式 ? ? ? ? mPaint.setStrokeWidth(10f);//畫筆寬度 ? ? ? ? mPath = new Path(); ? ? } ? ? @Override ? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec); ? ? ? ? width = getMeasuredWidth(); ? ? ? ? height = getMeasuredHeight(); ? ? ? ? if(mBitmap == null){ ? ? ? ? ?? ?// 初始化 bitmap ? ? ? ? ? ? mBitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_4444); ? ? ? ? } ? ? ? ? if(mCanvas == null){ ? ? ? ? ? ? mCanvas = new Canvas(mBitmap); ? ? ? ? } ? ? } ? ? @Override ? ? protected void onDraw(Canvas canvas) { ? ? ? ? super.onDraw(canvas); ? ? ? ? // 繪制路徑? ? ? ? ? // 因?yàn)槊看斡|摸都會(huì)生成一條新的路徑,直接繪制會(huì)使原路徑消失,因此 ? ? ? ? mCanvas.drawPath(mPath,mPaint);// 先將路徑繪制到 bitmap 上,再繪制到當(dāng)前畫布中 ? ? ? ? canvas.drawBitmap(mBitmap, 0,0,mPaint);// 將bitmap繪制到當(dāng)前畫布中 ? ? } ? ? /** ? ? ?* 清除之前所有路徑 ? ? ?*/ ? ? public void clearAllPath(){ ? ? ? ? mBitmap = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_4444); ? ? ? ? mCanvas = new Canvas(mBitmap); ? ? ? ? mPath.reset(); ? ? ? ? invalidate(); ? ? } ? ? /** ? ? ?* 設(shè)置畫筆顏色 ? ? ?* @param resource id ? ? ?*/ ? ? public void setPaintColor(int resource){ ? ? ? ? mPaint.setColor(mContext.getColor(resource)); ? ? } ? ? /** ? ? ?* 設(shè)置畫筆大小 ? ? ?* @param size size ? ? ?*/ ? ? public void setPaintSize(int size){ ? ? ? ? mPaint.setStrokeWidth(size); ? ? } ? ? @SuppressLint("ClickableViewAccessibility") ? ? @Override ? ? public boolean onTouchEvent(MotionEvent event) { ? ? ? ? int action = event.getAction(); ? ? ? ? float x = event.getX(); ? ? ? ? float y = event.getY(); ? ? ? ? switch (action){ ? ? ? ? ? ? case MotionEvent.ACTION_DOWN: ? ? ? ? ? ? ? ? mPath = new Path();// 每次觸摸 生成一條新的路徑 ? ? ? ? ? ? ? ? mPath.moveTo(x,y); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case MotionEvent.ACTION_MOVE: ? ? ? ? ? ? ? ? mPath.lineTo(x,y); ? ? ? ? ? ? ? ? invalidate(); ? ? ? ? ? ? ? ? break; ? ? ? ? } ? ? ? ? return true; ? ? } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android實(shí)現(xiàn)簡(jiǎn)單的畫畫板實(shí)例代碼
- Android實(shí)現(xiàn)畫板、寫字板功能(附源碼下載)
- Android自定義SurfaceView實(shí)現(xiàn)畫板功能
- Android采用雙緩沖技術(shù)實(shí)現(xiàn)畫板
- Android畫板開發(fā)之添加背景和保存畫板內(nèi)容為圖片
- Android畫板開發(fā)之橡皮擦功能
- Android實(shí)現(xiàn)畫畫板案例
- Android編程實(shí)現(xiàn)畫板功能的方法總結(jié)【附源碼下載】
- Android畫板開發(fā)之撤銷反撤銷功能
- Android多媒體之畫畫板開發(fā)案例分享
相關(guān)文章
Flutter配置代理抓包實(shí)現(xiàn)過程詳解
這篇文章主要為大家介紹了Flutter配置代理抓包實(shí)現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02Android用 Mob 實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼實(shí)例
這篇文章主要介紹了Android用 Mob 實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Android 架構(gòu)之?dāng)?shù)據(jù)庫(kù)框架升級(jí)
上一篇講解了# Android 架構(gòu)之?dāng)?shù)據(jù)框架搭建 ,里面含有數(shù)據(jù)庫(kù)最基礎(chǔ)的增刪改查功能,不過只考慮了單數(shù)據(jù)庫(kù),開發(fā)者可以舉一反三按照對(duì)應(yīng)思路設(shè)計(jì)多數(shù)據(jù)庫(kù)架構(gòu)。 在本篇里,將會(huì)講解令開發(fā)者比較頭疼的數(shù)據(jù)庫(kù)升級(jí),需要的朋友可以參考下面文章內(nèi)容2021-09-09Android啟動(dòng)初始化方案App StartUp的應(yīng)用詳解
這篇文章主要介紹了Android啟動(dòng)初始化方案App StartUp的使用方法,StartUp是為了App的啟動(dòng)提供的一套簡(jiǎn)單、高效的初始化方案,下面我們來詳細(xì)了解2022-09-09Android ListView實(shí)現(xiàn)上拉加載更多和下拉刷新功能
這篇文章主要為大家詳細(xì)介紹了Android ListView實(shí)現(xiàn)上拉加載更多和下拉刷新功能,介紹了ListView刷新原理及實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下2016-05-05Android自定義控件通用驗(yàn)證碼輸入框的實(shí)現(xiàn)
這篇文章主要介紹了Android自定義控件通用驗(yàn)證碼輸入框的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03PullToRefreshListView實(shí)現(xiàn)多條目加載上拉刷新和下拉加載
這篇文章主要為大家詳細(xì)介紹了PullToRefreshListView實(shí)現(xiàn)多條目加載上拉刷新和下拉加載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Android編程實(shí)現(xiàn)對(duì)話框Dialog背景透明功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)對(duì)話框Dialog背景透明功能,涉及Android對(duì)話框的布局、屬性及事件處理相關(guān)操作技巧,需要的朋友可以參考下2017-07-07Android自動(dòng)文本框輸入識(shí)別提示功能代碼
這篇文章主要介紹了Android開發(fā)之自動(dòng)文本框輸入識(shí)別提示功能代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07