Android实现手写板功能
更新时间:2022年06月29日 15:23:20 作者:伏辄
这篇文章主要为大家详细介绍了Android实现手写板功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud)
(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun)
本文实例为大家分享了Android实现手写板功能的具体代码,供大家参考,具体内容如下
自定义个一个手写板的重点:
笔画为一次down-move-up的集合
撤销笔画并非一次path的动作撤销 应该也是一次down-move -up的撤销
为了更好的笔画需要使用贝塞尔曲线来完成
效果如下:
截图中清楚 的意思是清除 !
具体代码如下:
package com.kyli.base.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; /** ?* 绘制画板 ?*/ public class SignBoradView extends View { ? ? /*4个像素点*/ ? ? private int beierThreshold = 4; ? ? private float x = 0; ? ? private float y = 0; ? ? /*画笔*/ ? ? private Paint mPaint; ? ? /*宽度*/ ? ? private int strokeWidth = 10; ? ? /*yanbse*/ ? ? private int color = Color.BLACK; ? ? /*当前笔画*/ ? ? private Path path; ? ? private int state = State.CLEAR; ? ? private interface State { ? ? ? ? /*画板可以使用了*/ ? ? ? ? int START = 0; ? ? ? ? /*停止使用画板*/ ? ? ? ? int STOP = 1; ? ? ? ? /*清空画板*/ ? ? ? ? int CLEAR = 2; ? ? } ? ? private List<EveryPenPath> everyPenPaths = new ArrayList<>(); ? ? /*每一个笔画*/ ? ? private static class EveryPenPath { ? ? ? ? public Path path; ? ? } ? ? public SignBoradView(Context context) { ? ? ? ? super(context); ? ? } ? ? public SignBoradView(Context context, @Nullable AttributeSet attrs) { ? ? ? ? super(context, attrs); ? ? } ? ? public SignBoradView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { ? ? ? ? super(context, attrs, defStyleAttr); ? ? } ? ? private void initPaint() { ? ? ? ? if (mPaint == null) { ? ? ? ? ? ? mPaint = new Paint(); ? ? ? ? ? ? mPaint.setStrokeWidth(strokeWidth); ? ? ? ? ? ? mPaint.setColor(color); ? ? ? ? ? ? mPaint.setStyle(Paint.Style.STROKE); ? ? ? ? ? ? mPaint.setAntiAlias(true); ? ? ? ? ? ? mPaint.setFlags(Paint.ANTI_ALIAS_FLAG); ? ? ? ? } ? ? } ? ? public void start() { ? ? ? ? state = State.START; ? ? ? ? initPaint(); ? ? } ? ? /*停止使用*/ ? ? public void stop() { ? ? ? ? state = State.STOP; ? ? } ? ? /*清空画板*/ ? ? public void clear() { ? ? ? ? state = State.CLEAR; ? ? ? ? for (int i = everyPenPaths.size() - 1; i >= 0; i--) { ? ? ? ? ? ? EveryPenPath everyPenPath = everyPenPaths.get(i); ? ? ? ? ? ? everyPenPath.path.reset(); ? ? ? ? ? ? everyPenPath.path.close(); ? ? ? ? ? ? everyPenPath.path = null; ? ? ? ? } ? ? ? ? everyPenPaths.clear(); ? ? ? ? invalidate(); ? ? } ? ? public void back() { ? ? ? ? int count = everyPenPaths.size(); ? ? ? ? if (count < 1) ? ? ? ? ? ? return; ? ? ? ? EveryPenPath everyPenPath = everyPenPaths.get(count - 1); ? ? ? ? everyPenPath.path.reset(); ? ? ? ? everyPenPath.path.close(); ? ? ? ? everyPenPath.path = null; ? ? ? ? everyPenPaths.remove(count - 1); ? ? ? ? invalidate(); ? ? } ? ? @Override ? ? protected void onDraw(Canvas canvas) { ? ? ? ? super.onDraw(canvas); ? ? ? ? if (state == State.START) { ? ? ? ? ? ? /*先绘制完整笔画*/ ? ? ? ? ? ? for (EveryPenPath e : everyPenPaths) { ? ? ? ? ? ? ? ? canvas.drawPath(e.path, mPaint); ? ? ? ? ? ? } ? ? ? ? ? ? //当前进行中的 ?path!=null ? ? ? ? ? ? if (path != null) { ? ? ? ? ? ? ? ? canvas.drawPath(path, mPaint); ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? @Override ? ? public boolean onTouchEvent(MotionEvent event) { ? ? ? ? if (state == State.START) { ? ? ? ? ? ? if (event.getAction() == MotionEvent.ACTION_UP) { ? ? ? ? ? ? ? ? actionUp(event); ? ? ? ? ? ? ? ? invalidate(); ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? } ? ? ? ? ? ? if (event.getAction() == MotionEvent.ACTION_MOVE) { ? ? ? ? ? ? ? ? actionMove(event); ? ? ? ? ? ? ? ? invalidate(); ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? } ? ? ? ? ? ? if (event.getAction() == MotionEvent.ACTION_DOWN) { ? ? ? ? ? ? ? ? actionDown(event); ? ? ? ? ? ? ? ? invalidate(); ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return super.onTouchEvent(event); ? ? } ? ? private void actionUp(MotionEvent event) { ? ? ? ? actionMove(event); ? ? ? ? /*构成一个笔画*/ ? ? ? ? EveryPenPath everyPenPath = new EveryPenPath(); ? ? ? ? everyPenPath.path = path; ? ? ? ? everyPenPaths.add(everyPenPath); ? ? ? ? //将当前画笔置位null; ? ? ? ? path = null; ? ? } ? ? /**/ ? ? private void actionMove(MotionEvent event) { ? ? ? ? /*每次移动去绘制贝塞尔曲线*/ ? ? ? ? float cX = event.getX(); ? ? ? ? float cY = event.getY(); ? ? ? ? float dX = Math.abs(cX - x);//变化量 ? ? ? ? float dY = Math.abs(cY - y); ? ? ? ? if (dX >= beierThreshold || dY >= beierThreshold) { ? ? ? ? ? ? float rX = x + (cX - x) / 2; ? ? ? ? ? ? float rY = y + (cY - y) / 2; ? ? ? ? ? ? path.quadTo(rX, rY, cX, cY); ? ? ? ? ? ? //下次的x 域y 将重新计算 ? ? ? ? ? ? x = cX; ? ? ? ? ? ? y = cY; ? ? ? ? } ? ? } ? ? /*开始时*/ ? ? private void actionDown(MotionEvent event) { ? ? ? ? path = new Path(); ? ? ? ? x = event.getX(); ? ? ? ? y = event.getY(); ? ? ? ? path.moveTo(x, y); ? ? } ? ? public void setBeierThreshold(int beierThreshold) { ? ? ? ? this.beierThreshold = beierThreshold; ? ? } ? ? public void setStrokeWidth(int strokeWidth) { ? ? ? ? this.strokeWidth = strokeWidth; ? ? } ? ? public void setColor(int color) { ? ? ? ? this.color = color; ? ? } ? ? public Bitmap getResult(int bgColor) { ? ? ? ? if (everyPenPaths.size() == 0) ? ? ? ? ? ? return null; ? ? ? ? Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); ? ? ? ? Canvas canvas = new Canvas(bitmap); ? ? ? ? canvas.drawColor(bgColor); ? ? ? ? for (int i = 0; i < everyPenPaths.size(); i++) { ? ? ? ? ? ? if (mPaint == null) { ? ? ? ? ? ? ? ? initPaint(); ? ? ? ? ? ? } ? ? ? ? ? ? canvas.drawPath(everyPenPaths.get(i).path, mPaint); ? ? ? ? } ? ? ? ? return bitmap; ? ? } ? ? public Bitmap getResult() { ? ? ? ? return getResult(Color.WHITE); ? ? } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。
您可能感兴趣的文章:
相关文章
Android实现美团、大众点评的购买悬浮效果(ScrollView滚动监听)
这篇文章主要为大家详细介绍了Android对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-02-02Android RecyclerView实现吸顶动态效果流程分析
RecyclerView是Android一个更强大的控件,其不仅可以实现和ListView同样的效果,还有优化了ListView中的各种不足。其可以实现数据纵向滚动,也可以实现横向滚动(ListView做不到横向滚动)。接下来讲解RecyclerView的用法2022-12-12Intel HAXM为Android 模拟器加速解决模拟器运行慢的问题
Android 模拟器一直以运行速度慢著称, 本文介绍使用 Intel HAXM 技术为 Android 模拟器加速, 使模拟器运行度媲美真机, 彻底解决模拟器运行慢的问题,感兴趣的朋友可以了解下哦2013-01-01Android自定义View 使用PathMeasure简单模仿系统ProgressBar(四)
这篇文章主要为大家详细介绍了Android自定义View,使用PathMeasure简单模仿系统ProgressBar,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-03-03
最新评论