设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间03 现在时间03 缓存数据 我的天 我居然可以遇见活的大佬

我的天 我居然可以遇见活的大佬 -- 空山新雨后

查看: 1850|回复: 3

自定义视图view使用Canvas实现手写板和涂鸦功能

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:205
  • 打卡月天数:0
  • 打卡总奖励:3160
  • 最近打卡:2023-08-27 06:04:43
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
428
主题
385
精华
0
金钱
4402
积分
841
注册时间
2022-12-21
最后登录
2025-3-13

发表于 2023-5-12 22:06:06 | 显示全部楼层 |阅读模式
预览图

230726zn77c8jmcdw0pz80.gif


一、xml布局
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3.     xmlns:android="http://schemas.android.com/apk/res/android"
  4.     android:id="@+id/activity_main"
  5.     android:layout_width="match_parent"
  6.     android:layout_height="match_parent"
  7.     android:orientation="vertical">

  8.     <LinearLayout
  9.         android:id="@+id/main_linlayout"
  10.         android:layout_width="match_parent"
  11.         android:layout_height="300dp"
  12.         android:orientation="vertical">
  13.     </LinearLayout>


  14.     <LinearLayout
  15.         android:layout_width="match_parent"
  16.         android:layout_height="wrap_content"
  17.         android:orientation="horizontal">
  18.         <Button
  19.             android:id="@+id/bt"
  20.             android:layout_width="match_parent"
  21.             android:layout_height="wrap_content"
  22.             android:layout_weight="1"
  23.             android:text="确定"/>
  24.         <Button
  25.             android:id="@+id/bt_clear"
  26.             android:layout_width="match_parent"
  27.             android:layout_height="wrap_content"
  28.             android:layout_weight="1"
  29.             android:text="清空"/>
  30.     </LinearLayout>

  31.     <ImageView
  32.         android:id="@+id/img"
  33.         android:layout_width="wrap_content"
  34.         android:layout_height="wrap_content"
  35.         android:layout_marginTop="5dp"
  36.         android:layout_gravity="center"/>
  37. </LinearLayout>
复制代码
布局预览图
230726qu222moababhvbbu.jpeg


二、MainActivity代码
  1. package tester.ermu.com.handdrawdemo;

  2. import android.app.Activity;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BlurMaskFilter;
  5. import android.graphics.EmbossMaskFilter;
  6. import android.os.Bundle;
  7. import android.util.DisplayMetrics;
  8. import android.view.View;
  9. import android.widget.Button;
  10. import android.widget.ImageView;
  11. import android.widget.LinearLayout;


  12. public class MainActivity extends Activity implements View.OnClickListener{
  13.     EmbossMaskFilter emboss;
  14.     BlurMaskFilter blur;
  15.     DrawView drawView;
  16.     private LinearLayout main_linlayout;
  17.     private Button bt,bt_clear;
  18.     private ImageView img;

  19.     @Override
  20.     public void onCreate(Bundle savedInstanceState) {
  21.         super.onCreate(savedInstanceState);
  22.         setContentView(R.layout.activity_main);
  23.         init(); //初始化组件
  24.         getWH();//获取我们xml布局中view的宽高
  25.     }

  26.     //获取我们xml布局中view的宽高
  27.     private void getWH() {
  28.         // 获取创建的宽度和高度
  29.         DisplayMetrics displayMetrics = new DisplayMetrics();
  30.         getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
  31.         // 创建一个DrawView,该DrawView的宽度、高度与该Activity保持相同
  32.         main_linlayout = (LinearLayout)findViewById(R.id.main_linlayout);
  33.         drawView = new DrawView(this, displayMetrics.widthPixels, displayMetrics.heightPixels);

  34.         main_linlayout.addView(drawView);
  35.         drawView.requestFocus();
  36.     }

  37.     private void init() {
  38.         bt = (Button)findViewById(R.id.bt);
  39.         bt.setOnClickListener(this);
  40.         bt_clear = (Button)findViewById(R.id.bt_clear);
  41.         bt_clear.setOnClickListener(this);

  42.         img = (ImageView) findViewById(R.id.img);
  43.     }

  44.     @Override
  45.     public void onClick(View v) {
  46.         switch (v.getId()){
  47.             case R.id.bt:
  48.                 Bitmap bit = drawView.getPaintBitmap();
  49.                 img .setImageBitmap(bit);
  50.                 break;

  51.             case R.id.bt_clear:
  52.                 drawView.clear();

  53.                 break;
  54.         }
  55.     }
  56. }
复制代码
三、我们自定义view的类
  1. package tester.ermu.com.handdrawdemo;

  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.Canvas;
  5. import android.graphics.Color;
  6. import android.graphics.Matrix;
  7. import android.graphics.Paint;
  8. import android.graphics.Path;
  9. import android.graphics.PorterDuff;
  10. import android.util.AttributeSet;
  11. import android.view.MotionEvent;
  12. import android.view.View;

  13. public class DrawView extends View {
  14.     // 定义记录前一个拖动事件发生点的坐标
  15.     float preX;
  16.     float preY;
  17.     private Path path;
  18.     public Paint paint = null;
  19.     // 定义一个内存中的图片,该图片将作为缓冲区
  20.     Bitmap cacheBitmap = null;
  21.     // 定义cacheBitmap上的Canvas对象
  22.     Canvas cacheCanvas = null;

  23.     public DrawView(Context context) {
  24.         super(context);
  25.     }

  26.     public DrawView(Context context, AttributeSet attrs) {
  27.         super(context, attrs);
  28.     }

  29.     public DrawView(Context context, int width , int height) {
  30.         super(context);
  31.         // 创建一个与该View相同大小的缓存区
  32.         cacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
  33.         cacheCanvas = new Canvas();
  34.         path = new Path();
  35.         // 设置cacheCanvas将会绘制到内存中的cacheBitmap上
  36.         cacheCanvas.setBitmap(cacheBitmap);
  37.         // 设置画笔的颜色
  38.         paint = new Paint(Paint.DITHER_FLAG);
  39.         paint.setColor(Color.RED);
  40.         // 设置画笔风格
  41.         paint.setStyle(Paint.Style.STROKE);
  42.         paint.setStrokeWidth(3);
  43.         // 反锯齿
  44.         paint.setAntiAlias(true);
  45.         paint.setDither(true);
  46.     }

  47.     @Override
  48.     public boolean onTouchEvent(MotionEvent event)
  49.     {
  50.         // 获取拖动事件的发生位置
  51.         float x = event.getX();
  52.         float y = event.getY();
  53.         switch (event.getAction())
  54.         {
  55.             case MotionEvent.ACTION_DOWN:
  56.                 // 从前一个点绘制到当前点之后,把当前点定义成下次绘制的前一个点
  57.                 path.moveTo(x, y);
  58.                 preX = x;
  59.                 preY = y;
  60.                 break;
  61.             case MotionEvent.ACTION_MOVE:
  62.                 // 从前一个点绘制到当前点之后,把当前点定义成下次绘制的前一个点
  63.                 path.quadTo(preX, preY, x, y);
  64.                 preX = x;
  65.                 preY = y;
  66.                 break;
  67.             case MotionEvent.ACTION_UP:
  68.                 cacheCanvas.drawPath(path, paint); // ①
  69.                 path.reset();
  70.                 break;
  71.         }
  72.         invalidate();
  73.         // 返回true表明处理方法已经处理该事件
  74.         return true;
  75.     }
  76.     @Override
  77.     public void onDraw(Canvas canvas)
  78.     {
  79.         Paint bmpPaint = new Paint();
  80.         // 将cacheBitmap绘制到该View组件上
  81.         canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint); // ②
  82.         // 沿着path绘制
  83.         canvas.drawPath(path, paint);
  84.     }

  85.     //获取我们绘制成功后的图片

  86.     public Bitmap getPaintBitmap() {
  87.         return resizeImage(cacheBitmap, 620, 780);
  88.     }



  89.     // 缩放
  90.     public static Bitmap resizeImage(Bitmap bitmap, int width, int height) {
  91.         //获取图片的宽高
  92.         int originWidth = bitmap.getWidth();
  93.         int originHeight = bitmap.getHeight();

  94.         //这里缩放我们的尺寸,缩放多少自己去定义
  95.         float scaleWidth = ((float) width) / originWidth;
  96.         float scaleHeight = ((float) height) / originHeight;

  97.         //进行缩放
  98.         Matrix matrix = new Matrix();
  99.         matrix.postScale(scaleWidth, scaleHeight);
  100.         Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, originWidth,
  101.                 originHeight, matrix, true);
  102.         return resizedBitmap;
  103.     }


  104.     //清除画板
  105.     public void clear() {
  106.         if (cacheBitmap != null) {
  107.             path.reset();
  108.             cacheCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
  109.             invalidate();
  110.         }
  111.     }
  112. }
复制代码
到此这篇关于自定义视图view使用Canvas实现手写板和涂鸦功能的文章就介绍到这了,更多相关自定义视图Canvas手写板涂鸦内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
16
积分
12
注册时间
2022-12-27
最后登录
2022-12-27

发表于 2024-9-10 22:41:12 | 显示全部楼层
路过,支持一下
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
1
精华
0
金钱
40
积分
23
注册时间
2022-12-25
最后登录
2023-5-19

发表于 2024-12-1 12:45:51 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

  • 打卡等级:即来则安
  • 打卡总天数:22
  • 打卡月天数:0
  • 打卡总奖励:293
  • 最近打卡:2025-06-28 08:52:33
等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
333
积分
48
注册时间
2023-3-10
最后登录
2025-6-28

发表于 2025-4-7 05:25:46 | 显示全部楼层
感谢楼主分享。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼
4楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表