准备
我们需要一个Activity以及对应的布局文件,当然也可以用fragment;
在布局文件中,添加一个放置图片的ImageView控件,并设置好图片和ID。
这是我的Activity和布局文件,已经设置好图片和ID的ImageView控件:
图片描述
开始
在Activity中绑定控件(这里我用的butterknife快速绑定),创建三个常量,表示手指的三种状态:抬起,缩放,拖拽;创建一个变量,记录这三种状态:
@BindView(R.id.img)
ImageView img;
private final int NONE=0;//抬起
private final int ZOOM=1;//缩放
private final int DRAG=2;//拖拽
private int status=NONE;//存储当前状态
private double lastDis;
再创建两个PointF对象和两个Matrix对象,干什么用的,已经写在注释里面了:
PointF midPoint=new PointF();//当两根手指放下时,记录两根手指中点坐标
PointF startPoint=new PointF();//当一根手指放下时,记录当前坐标
Matrix matrix=new Matrix();//用于变换图片的矩阵
Matrix savedMatrix=new Matrix();//用于存储矩阵信息
在onCreate()方法中设置图片的缩放方式为矩阵缩放:
img.setScaleType(ImageView.ScaleType.MATRIX);//设置图片的缩放方式
重写onTouchEvent()方法:
/**
* 当单指放下时,用先用matrix保存图片信息,再将matrix的值赋给savedMatrix,startPoint记录当前坐标,status记录当前状态;
* 当双指放下时,lastDis记录两指之间的距离,将matrix当前值付给savedMatrix,midPoint记录两指的中点坐标,status记录当前状态。
*
* 当手指开始移动时,根据status的值决定移动还是缩放;
* 如果是移动,将savedMatrix的值赋给matrix,调用matrix.postTranslate()方法,更改matrix的值;
* 如果是缩放,获取当前手指之间的距离,同样将savedMatrix的值赋给matrix,调用matrix.postScale()方法更改matrix的值。
*
* 最后再switch语句外边,调用img.setImageMatrix()变换图片。
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (MotionEvent.ACTION_MASK&event.getAction()){
case MotionEvent.ACTION_DOWN:
matrix.set(img.getImageMatrix());
savedMatrix.set(matrix);
startPoint.set(event.getX(),event.getY());
status=DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
lastDis=getFingerDis(event);
savedMatrix.set(matrix);
midPoint=getMidPoint(event);
status=ZOOM;
break;
case MotionEvent.ACTION_MOVE:
switch (status){
case DRAG:
matrix.set(savedMatrix);
matrix.postTranslate(event.getX()-startPoint.x,event.getY()-startPoint.y);
break;
case ZOOM:
double curDis=getFingerDis(event);
float scaleMul= (float) (curDis/lastDis);
matrix.set(savedMatrix);
matrix.postScale(scaleMul,scaleMul,midPoint.x,midPoint.y);
break;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
status=NONE;
break;
}
img.setImageMatrix(matrix);//让图片根据矩阵信息变化(平移或缩放)
return true;
}
获取两点间距离的方法:
private double getFingerDis(MotionEvent e){
double disX=Math.abs(e.getX(0)-e.getX(1));
double disY=Math.abs(e.getY(0)-e.getY(1));
return Math.sqrt(disX*disX+disY*disY);
}
获取两点间中点坐标的方法:
private PointF getMidPoint(MotionEvent e){
float midX=(e.getX(0)+e.getX(1))/2;
float midY=(e.getY(0)+e.getY(1))/2;
return new PointF(midX,midY);
}