自定义视图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>
布局预览图
二、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
0
投稿
猜你喜欢
- 本文实例为大家分享了Java中Stream流去除List重复元素的具体代码,供大家参考,具体内容如下业务场景在开发中我们常常需要过滤List
- 在我们的web开发中,很多的时候都需要把本机的一些文件上传到web服务器上面去。如:一个BBS系统,当用户使用这是系统的时候,能把本机的一些
- 一个activity就好比一个网页,此文章讲解怎样创建一个activity并且实现跳转!一、学习创建Activity1、新建一个java类,
- 不知道大家对千篇一律的404 Not Found的错误页面是否感到腻歪了?其实通过很简单的配置就能够让Spring MVC显示您自定义的40
- @Autowired注入static接口问题@Autowired自动注入普通service很方便如:@Componentpublic cla
- 背景最近再做一个需求,就是对站点的一些事件进行埋点,说白了就是记录用户的访问行为。那么这些数据怎么保存呢,人家点一下保存一下?显然不合适,肯
- 这两天实现了下新手引导需要的遮罩镂空shader效果,记录一下。1、圆形镂空shader代码:  
- 在项目迁移到Spring Boot之后,发生内存使用量过高的问题。本文介绍了整个排查过程以及使用到的工具,也非常适用于其他堆外内存排查。背景
- 下载maven 解压路径: 打开环境变量:右键此电脑-属性-高级系统设置-高级-环境变量添加以下系统变量:测试:win+
- 一、项目简述(+需求文档+PPT)功能: 主页显示热销商品;所有商品展示,可进行商品搜索;点 击商品进入商品详情页,显示库存,具有立即购买和
- 最近有个老项目想逐步将新业务的数据放到新的数据库,以前的业务还得连接以前的数据库,于是需要整合多数据源 。多数据源实际上是继承了Abstra
- 一些初学Android的朋友可能会遇到JAVA的数据类型之间转换的苦恼,例如,整数和float,double型之间的转换,整数和String
- 对于maven的部署和安装插件不熟的同学可以看一下上两篇文章maven的部署和安装:此笔记已经集成了maven的插件。一、构建Maven项目
- 新公司工程是用Maven管理的,技术上使用了JPA,但是我导入工程到MyEclipse时,applicationContext.xml中提示
- 其实如果我们不进行设置,只是修改了代码,运行程序以后,其出错界面如下图1所示:图1抛出异常如下:************** Excepti
- 前言Jetpack Compose(简称 Compose )是 Google 官方推出的基于 Kotlin 语言的 Android 新一代
- 本地jvm执行flink带web ui使用StreamExecutionEnvironment executionEnvironment =
- 可以使用 Java 8 中的 Map.replaceAll() 方法将所有的值转为 String 类型:Map<String, Obj
- 本文实例为大家分享了Android自定义带圆点的半圆形进度条,供大家参考,具体内容如下仅限用于半圆形,如须要带圆点的圆形进度条,圆点会出现错
- java简易小游戏制作游戏思路:设置人物移动,游戏规则,积分系统,随机移动的怪物,游戏胜负判定,定时器。游戏内容部分package 代码部分