Android中对图片的操作,移动、缩放、涂鸦和保存到图库

一、实现方法

监听用户手势,提取用户操作
(1)移动: 分别计算X,Y轴的结束与初始之间移动偏移的量
(2)缩放:(结束两指间距离×伸缩比例)/ 初始两指间距离,scaleX,scaleY放大多少倍
(3)涂鸦:重写onDraw()方法,画布(canvas)结合画笔(Paint)构造Path实现,监听手势起始点坐标与结束坐标,使用path类的quadTo()方法绘制曲线
(4)保存:保存图片Insert到MediaStore.Images.Media下面,广播通知系统相册图库刷新数据

二、demo

在这里插入图片描述

1、移动缩放

通过 Matrix 矩阵 方式操作图片

    private static final int NONE = 0;
    private static final int DRAG = 1; //一个手指
    private static final int ZOOM = 2; //两个手指
    private int mode = NONE;

    private Matrix matrix = new Matrix();  //移动的矩阵
    private Matrix saveMatrix = new Matrix();
    private PointF startPoint = new PointF(); //第一个按下手指的点
    private PointF midPoint = new PointF();  // 两个按下手指触摸点的中点
    private float distance = 1f; //两个手指触摸点之间的距离

ImageView图片控件的监听

        imageView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                return true;
            }
        });
        imageView.setOnTouchListener((view, motionEvent) -> {
            ImageView imageView = (ImageView) view;
            imageView.setScaleType(ImageView.ScaleType.MATRIX);  //注意:操作之前需设置ScaleType为matrix
//            final int x = (int) motionEvent.getRawX();  //触摸点到屏幕左边的距离
//            final int y = (int) motionEvent.getRawY();  //触摸点到屏幕上边的距离
//            Log.i(TAG,"触摸点离屏幕左边的距离:"+ x +"屏幕上方的距离:"+ y);
            switch (motionEvent.getAction() & MotionEvent.ACTION_MASK){
                case MotionEvent.ACTION_DOWN:
                    Log.i(TAG,"单点按下");
                    //单点按下
                    mode = DRAG;
                    //设置要操作的矩阵为该图片的图片矩阵
                    matrix.set(imageView.getImageMatrix());
                    saveMatrix.set(matrix);
                    startPoint.set(motionEvent.getX(),motionEvent.getY());
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    //多点按下
                    Log.i(TAG,"多点按下");
                    //计算两指间距离
                    distance = distance(motionEvent);
                    if (distance > 10f){
                        saveMatrix.set(matrix);
                        //计算两指间中点的坐标
                        midPoint = midPoint(motionEvent);
                        mode = ZOOM;
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    //手指滑动
                    if (mode == DRAG){
                        Log.i(TAG,"移动");
                        //获取当前图片矩阵
                        matrix.set(saveMatrix);
                        //分别在x、y轴上将图片矩阵移动相应的距离
                        matrix.postTranslate(motionEvent.getX() - startPoint.x,motionEvent.getY() - startPoint.y);
                    }else if(mode == ZOOM){
                        Log.i(TAG,"缩放");
                        float newDistance = distance(motionEvent);
                        if (newDistance > 10f){
                            //获取当前图片矩阵
                            matrix.set(saveMatrix);
                            //放大或缩小的倍数(缩放后手指间的距离/缩放前手指间的距离)
                            float scale = newDistance/distance;
                            //以两指中点为中心将当前图片矩阵放大或缩小scale倍
                            matrix.postScale(scale,scale,midPoint.x,midPoint.y);
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                    //手指抬起
                    mode = NONE;
                    break;
                default:
                    break;
            }
            //将操作后的图片矩阵赋值给imageView
            imageView.setImageMatrix(matrix);
            return true;
        });

计算两指间距离

    private float distance(MotionEvent motionEvent){
        float dx = motionEvent.getX(0) - motionEvent.getX(1);
        float dy = motionEvent.getY(0) - motionEvent.getY(1);
        return (float) Math.sqrt(dx * dx + dy * dy);
    }

计算两指间中点的坐标

    private PointF midPoint(MotionEvent motionEvent){
        float midx = (motionEvent.getX(0) + motionEvent.getX(1)) / 2;
        float midy = (motionEvent.getY(0) + motionEvent.getY(1)) / 2;
        return new PointF(midx,midy);
    }

控件布局,注意根据情况设置scaleType

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:scaleType="fitCenter"
        android:src="@drawable/bbb"
        app:layout_constraintBottom_toTopOf="@+id/tv_start"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/state" />

2、涂鸦

持续更新中

猜你喜欢

转载自blog.csdn.net/qq_46269365/article/details/128847360