網(wǎng)站首頁 編程語言 正文
本文實(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;
? ? }
}
原文鏈接:https://blog.csdn.net/yubaba111/article/details/122494507
相關(guān)推薦
- 2022-04-07 c++中的volatile和variant關(guān)鍵字詳解_C 語言
- 2022-11-13 Python四大模塊文件管理介紹_python
- 2022-06-06 Array.prototype.myfindIndex
- 2022-11-16 Python中dataclass庫實(shí)例詳解_python
- 2022-04-30 C#操作DataGridView設(shè)置單元格只讀_C#教程
- 2022-04-03 C++從匯編的視角審視對(duì)象的創(chuàng)建問題_C 語言
- 2023-07-26 webpack打包優(yōu)化之減少代碼體積(Tree shaking、babel)
- 2022-08-16 C++深入了解模板的使用_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支