从零开始实现Android自定义手写画板

从零开始实现Android自定义手写画板

最近需要实现一个手写签名控件,在搜索多轮后,终于实现了效果,但是一个手写签名,涉及到了自定义View,画板,path等知识发现自己还是有挺多地方不清楚的,下面从零开始实现一个自定义画板,也一个个解释用到的知识点,算是对手写签名用到所需知识的一个总结。

手写顾名思义是在屏幕中获取若干不连续的点,然后把这些点连成一条线。

1.构造方法里面初始化画布背景、画笔、和路径

public class PaintView extends View {
    
    private Paint mPaint;
    private Canvas cacheCanvas;
    private Path mPath;
    private Bitmap mCachebBitmap;
    
    public PaintView(Context context) {
        super(context);
    }

    public PaintView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    
    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(4.0f);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.BLACK);
        mPath = new Path();
    }
}

Paint

我们知道在画板上画画,需要一直画笔,Paint 类你可以想象它就是一支画笔,通过Paint ,你可以设置画笔的大小,颜色等等。

Path

Path 封装了直线,二次曲线和三次曲线组成的复合路径,在手写签名中,我们每在屏幕中移动,就会产生一个路径,我们需要把这个路径通过Path记录下来,在配合Canvas .drawPath(Path path,Paint paint)绘制在画板上。

2.初始化画板

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   		             super.onMeasure(widthMeasureSpec, heightMeasureSpec);   
    mCachebBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),         Bitmap.Config.ARGB_8888);    
    cacheCanvas = new Canvas(mCachebBitmap); //canvas绘制的内容,将会在这个mCachebBitmap内   
}

在onMeasure中,等控件初始化完成,可以获取宽高时,初始化缓存的Bitmap和画板。

下面附上完整的代码

public class PaintView extends View {

    AttributeSet attrs;
    private Paint mPaint;
    private Canvas cacheCanvas;
    private Path mPath;
    private Bitmap mCachebBitmap;

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

    public PaintView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(4.0f);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.BLACK);
        
        mPath = new Path();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mCachebBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        //canvas绘制的内容,将会在这个mBufferBitmap内
        cacheCanvas = new Canvas(mCachebBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mCachebBitmap, 0, 0, null);
    }

    private float mLastTouchX, mLastTouchY;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float eventX = event.getX();
        float eventY = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                mPath.moveTo(eventX, eventY);
                mLastTouchX = eventX;
                mLastTouchY = eventY;
                break;
            }

            case MotionEvent.ACTION_MOVE:
                mPath.quadTo(mLastTouchX, mLastTouchY, eventX, eventY);
                //在缓存里面绘制
                cacheCanvas.drawPath(mPath, mPaint);
                //重新绘制,会调用onDraw方法
                invalidate();
                mLastTouchX = eventX;
                mLastTouchY = eventY;
                break;
            case MotionEvent.ACTION_UP: {
                mPath.reset();
                break;
            }
        }
        return true;
    }
}

现在一个最简单手写画板就实现了

可以发现实现手写的重点在于onTouchEvent方法中,那么我们来看看该方法。

当我们手指落下屏幕时,触发onTouchEvent的MotionEvent.ACTION_DOWN回调,调用了mPath.moveTo(eventX, eventY),这里可以把path的起始坐标移动到eventX,eventY,即我们手指落下的位置。

当我们手指在屏幕中移动时,触发MotionEvent.ACTION_MOVE,调用了mPath.quadTo(mLastTouchX, mLastTouchY, eventX, eventY); 把我们手指落下屏幕的坐标mLastTouchX,mLastTouchY作为起点,手指移动的终点坐标eventX,eventY,用来绘制一个曲线。

cacheCanvas.drawPath(mPath, mPaint);

后需要把这个路径存储起来,并调用invalidate();方法,这时会回调

@Override
protected void onDraw(Canvas canvas) {    
    canvas.drawBitmap(mCachebBitmap, 0, 0, null);
}

这时才真正的把手写线画到了界面上。

当然后续还有刷新优化,导出图片,擦除画笔等内容,这些我们后边继续。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值