Android触摸事件实现笔触画布

作者: e4e52c116681 | 来源:发表于2018-10-30 15:44 被阅读7次

    任何View都有触摸事件,经常在自定义控件时重写setOnTouchListener
    本篇通过手绘图片来讲述这个知识点

    本篇分为三个等级:一览图:
    直线 曲线 笔触
    LEVEL1.png LEVEL2.png LEVER3.png

    LEVEL1:基础实现

    在Activity中通过一个全屏的Bitmap创建的Canvas绘制
    为ImageView添加触摸事件监听。

    1.成员变量
    ImageView mIdIvShow;
    float downX = 0;
    float downY = 0;
    float upX = 0;
    float upY = 0;
    private Canvas mCanvas;
    private Paint mPaint;
    
    2.创建画布
    //获取屏幕尺寸
    Point point = new Point();
    getWindowManager().getDefaultDisplay().getSize(point);
    
    //创建一个和屏幕一样大的Bitmap
    Bitmap bitmap = Bitmap.createBitmap(point.x, point.y, Bitmap.Config.ARGB_8888);
    //创建Canvas对象
    mCanvas = new Canvas(bitmap);
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setStrokeWidth(10);
    mPaint.setColor(Color.RED);
    //将bitmap用ImageView展示
    mIdIvShow.setImageBitmap(bitmap);
    
    3.监听事件
     mIdIvShow.setOnTouchListener((v, event) -> {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        downX = event.getX();
                        downY = event.getY();
                        L.d("按下:(" + downX + "," + downY + ")" + L.l());
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        break;
                    case MotionEvent.ACTION_MOVE:
                        break;
                    case MotionEvent.ACTION_UP:
                        upX = event.getX();
                        upY = event.getY();
                        L.d("抬起:(" + upX + "," + upY + ")" + L.l());
                        mCanvas.drawLine(downX, downY, upX, upY, mPaint);
                        mIdIvShow.invalidate();//更新视图
                        break;
                }
                return true;
            });
        }
    

    升级版:LEVER2

    LEVEL2.png
    mIdIvShow.setOnTouchListener((v, event) -> {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            case MotionEvent.ACTION_MOVE:
                upX = event.getX();
                upY = event.getY();
                mCanvas.drawLine(downX, downY, upX, upY, mPaint);
                mIdIvShow.invalidate();
                //更新点位
                downY = upY;
                downX = upX;
                break;
            case MotionEvent.ACTION_UP:
                //抬起点Y>1100,清除笔迹
                if (upY > 1100) {
                    Paint paint = new Paint();
                    paint.setColor(Color.WHITE);
                    mCanvas.drawRect(0, 0, mPoint.x, mPoint.y, paint);
                }
                break;
        }
        return true;
    });
    

    再升级版:LEVER3

    笔触根据绘制的速度动态改变画笔粗细

    LEVER3.png
    float movingX = 0;
    float movingY = 0;
    private long lastTimestamp = 0L;//最后一次的时间戳
    
    mIdIvShow.setOnTouchListener((view, event) -> {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastTimestamp = System.currentTimeMillis();
                downX = event.getX();
                downY = event.getY();
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            case MotionEvent.ACTION_MOVE:
                movingX = event.getX();
                movingY = event.getY();
                long curTimestamp = System.currentTimeMillis();
                //计算时间差
                long detaT = curTimestamp - lastTimestamp;
                //计算距离差
                float detaS = Logic.disPos2d(movingX, movingY, downX, downY);
                //由于速度是 px/ms
                double v = detaS / detaT;
                //速度转化为画笔宽度的等式
                float width = 14/(float)v;
                L.d(width + L.l());
                //限制极值情况
                if ((width > 0) && width < 30) {
                    mPaint.setStrokeWidth(width);
                }
                mCanvas.drawLine(downX, downY, movingX, movingY, mPaint);
                mIdIvShow.invalidate();
                downX = movingX;
                downY = movingY;
                lastTimestamp = curTimestamp;//更新时间
                movePos.add(new PointF(event.getX(), event.getY()));
                break;
        }
        return true;
    });
    

    拓展

    1.其中可以改变求宽度的等式实现不同的笔触:如
    float width = (float) Math.log10(v) * 40;
    
    LEVER3+.png
    2.在图片上绘画
    //图片原型
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.iv_500x400);
    //图片副本
    Bitmap mNewBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
    //用副本生成Canvas
    mCanvas = new Canvas(mNewBitmap);
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    mPaint.setStrokeCap(Paint.Cap.ROUND);//直线圆头
    mCanvas.drawBitmap(bitmap, new Matrix(), mPaint);
    mPaint.setStrokeWidth(10);
    mPaint.setColor(Color.parseColor("#88164BE6"));
    //设置副本图片到ImageView
    mIdIvShow.setImageBitmap(mNewBitmap);
    
    拓展2.png

    后记:捷文规范

    1.本文成长记录及勘误表
    项目源码 日期 备注
    V0.1--无 2018-10-30 Android触摸事件实现笔触画布
    2.更多关于我
    笔名 QQ 微信 爱好
    张风捷特烈 1981462002 zdl1994328 语言
    我的github 我的简书 我的CSDN 个人网站
    3.声明

    1----本文由张风捷特烈原创,转载请注明
    2----欢迎广大编程爱好者共同交流
    3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
    4----看到这里,我在此感谢你的喜欢与支持

    相关文章

      网友评论

        本文标题:Android触摸事件实现笔触画布

        本文链接:https://www.haomeiwen.com/subject/etvgtqtx.html