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

作者:小白的成长之路 时间:2022-02-22 17:00:43 

预览图

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

一、xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/activity_main"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical">

<LinearLayout
       android:id="@+id/main_linlayout"
       android:layout_width="match_parent"
       android:layout_height="300dp"
       android:orientation="vertical">
   </LinearLayout>

<LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal">
       <Button
           android:id="@+id/bt"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_weight="1"
           android:text="确定"/>
       <Button
           android:id="@+id/bt_clear"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:layout_weight="1"
           android:text="清空"/>
   </LinearLayout>

<ImageView
       android:id="@+id/img"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginTop="5dp"
       android:layout_gravity="center"/>
</LinearLayout>

布局预览图

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

二、MainActivity代码

package tester.ermu.com.handdrawdemo;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.EmbossMaskFilter;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends Activity implements View.OnClickListener{
   EmbossMaskFilter emboss;
   BlurMaskFilter blur;
   DrawView drawView;
   private LinearLayout main_linlayout;
   private Button bt,bt_clear;
   private ImageView img;

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

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

main_linlayout.addView(drawView);
       drawView.requestFocus();
   }

private void init() {
       bt = (Button)findViewById(R.id.bt);
       bt.setOnClickListener(this);
       bt_clear = (Button)findViewById(R.id.bt_clear);
       bt_clear.setOnClickListener(this);

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

@Override
   public void onClick(View v) {
       switch (v.getId()){
           case R.id.bt:
               Bitmap bit = drawView.getPaintBitmap();
               img .setImageBitmap(bit);
               break;

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

break;
       }
   }
}

三、我们自定义view的类

package tester.ermu.com.handdrawdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

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

public DrawView(Context context) {
       super(context);
   }

public DrawView(Context context, AttributeSet attrs) {
       super(context, attrs);
   }

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

@Override
   public boolean onTouchEvent(MotionEvent event)
   {
       // 获取拖动事件的发生位置
       float x = event.getX();
       float y = event.getY();
       switch (event.getAction())
       {
           case MotionEvent.ACTION_DOWN:
               // 从前一个点绘制到当前点之后,把当前点定义成下次绘制的前一个点
               path.moveTo(x, y);
               preX = x;
               preY = y;
               break;
           case MotionEvent.ACTION_MOVE:
               // 从前一个点绘制到当前点之后,把当前点定义成下次绘制的前一个点
               path.quadTo(preX, preY, x, y);
               preX = x;
               preY = y;
               break;
           case MotionEvent.ACTION_UP:
               cacheCanvas.drawPath(path, paint); // ①
               path.reset();
               break;
       }
       invalidate();
       // 返回true表明处理方法已经处理该事件
       return true;
   }
   @Override
   public void onDraw(Canvas canvas)
   {
       Paint bmpPaint = new Paint();
       // 将cacheBitmap绘制到该View组件上
       canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint); // ②
       // 沿着path绘制
       canvas.drawPath(path, paint);
   }

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

public Bitmap getPaintBitmap() {
       return resizeImage(cacheBitmap, 620, 780);
   }

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

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

//进行缩放
       Matrix matrix = new Matrix();
       matrix.postScale(scaleWidth, scaleHeight);
       Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, originWidth,
               originHeight, matrix, true);
       return resizedBitmap;
   }

//清除画板
   public void clear() {
       if (cacheBitmap != null) {
           path.reset();
           cacheCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
           invalidate();
       }
   }
}

来源:https://blog.csdn.net/bobo8945510/article/details/53256863

标签:自定义,视图,view,Canvas,手写板,涂鸦
0
投稿

猜你喜欢

  • Flutter自定义圆盘取色器

    2023-07-05 23:55:43
  • java 查找替换pdf中的指定文本

    2022-08-17 14:04:46
  • 详解Spring-boot中读取config配置文件的两种方式

    2021-07-04 15:52:55
  • JDK8中的HashMap初始化和扩容机制详解

    2023-11-25 10:06:44
  • Java基础学习之构造方法详解

    2021-06-16 16:25:53
  • C# MVC 使用LayUI实现下拉框二级联动的功能

    2022-12-07 02:10:05
  • java图片识别文字的方法

    2021-11-11 02:43:03
  • java实现简单银行家算法

    2022-01-31 23:33:19
  • Spring Boot实现JWT token自动续期的实现

    2022-02-12 03:48:40
  • Spring AOP的底层实现方式-代理模式

    2022-10-05 23:27:50
  • zookeeper实现分布式锁

    2023-08-03 13:44:18
  • C#与js实现去除textbox文本框里面重复记录的方法

    2022-08-02 03:14:06
  • Mybatis代码生成器Mybatis Generator(MBG)实战详解

    2023-12-02 23:04:31
  • java @Value(

    2023-10-05 02:54:47
  • Java 高并发五:JDK并发包1详细介绍

    2022-11-29 08:56:26
  • JAVA swing布局管理器实例解析

    2022-01-11 05:05:15
  • C#中的一些延时函数

    2023-11-29 04:33:30
  • Java结构型设计模式中建造者模式示例详解

    2023-04-24 13:37:31
  • Java8新特性之泛型的目标类型推断_动力节点Java学院整理

    2023-11-26 10:38:21
  • SpringMVC 如何使用注解完成登录拦截

    2023-11-18 02:20:11
  • asp之家 软件编程 m.aspxhome.com