一、实现方法
监听用户手势,提取用户操作
(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、涂鸦
持续更新中