Muilti-touch 双指缩放的实现
首先要实现OnTouchListener接口,然后重写方法:
public boolean onTouch(View v, MotionEvent event);
从这个方法中我们就可以获取实现两指缩放功能的全部信息。
View v是触发事件的源,MotionEvent event即一个触摸事件。对屏幕的几乎所有操作都会触发事件,如点击、放开、滑动等。
不同的事件在MotionEvent中有不同的id,我们可以根据event.getAction() & MotionEvent.ACTION_MASK的结果来判断是何种事件。其实就是event.getActionMasked().
有如下事件使我们要用到的:
- MotionEvent.ACTION_DOWN:在第一个点被按下时触发
- MotionEvent.ACTION_UP:当屏幕上唯一的点被放开时触发
- MotionEvent.ACTION_POINTER_DOWN:当屏幕上已经有一个点被按住,此时再按下其他点时触发。
- MotionEvent.ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)。
- MotionEvent.ACTION_MOVE:当有点在屏幕上移动时触发。值得注意的是,由于它的灵敏度很高,而我们的手指又不可能完全静止(即使我们感觉不到移动,但其实我们的手指也在不停地抖动),所以实际的情况是,基本上只要有点在屏幕上,此事件就会一直不停地被触发。
举例子来说:当我们放一个食指到屏幕上时,触发ACTION_DOWN事件;再放一个中指到屏幕上,触发ACTION_POINTER_DOWN事件;此时再把食指或中指放开,都会触发ACTION_POINTER_UP事件;再放开最后一个手指,触发ACTION_UP事件;而同时在整个过程中,ACTION_MOVE事件会一直不停地被触发。
event.getX(index)和event.getY(index)可以获取到指定index点的坐标,所以当屏幕上有两个点的时候,我们用如下方法来获取两点间的距离:
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
代码如下:
package com.kelly.dragscale;
import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageview);
imageView.setOnTouchListener(new TouchListener());
}
private class TouchListener implements OnTouchListener {
private PointF startPointF = new PointF();
private Matrix matrix = new Matrix();
private Matrix currentMatrix = new Matrix();
private int mode = 0;
private static final int DRAG = 1;//拖拉
private static final int ZOOM = 2;//缩放
float startDis = 0;// 开始距离
float endDis = 0;// 结束距离
private PointF midF = new PointF();
public boolean onTouch(View v, MotionEvent event) {
//event.getActionMasked();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN://
mode = DRAG;
currentMatrix.set(imageView.getImageMatrix());// 记录imageview当前的移动位置
startPointF.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE://
if (mode == DRAG)// 拖拉模式
{
float dx = event.getX() - startPointF.x;
float dy = event.getY() - startPointF.y;
matrix.set(currentMatrix);// 在上一次移动的基础上进行移动
matrix.postTranslate(dx, dy);
} else if (mode == ZOOM) {// 缩放模式
endDis = distance(event);
if (endDis > 10f) {
float scale = endDis / startDis;
matrix.set(currentMatrix);
matrix.postScale(scale, scale, midF.x, midF.y);
}
}
break;
case MotionEvent.ACTION_UP://
break;
case MotionEvent.ACTION_POINTER_DOWN:// 当屏幕上已经有触电(手指),再有一个手指按下
mode = ZOOM;
startDis = distance(event);
if (startDis > 10f) {
midF = getMid(event);
currentMatrix.set(imageView.getImageMatrix());// 记录imageview当前的缩放倍数
}
break;
case MotionEvent.ACTION_POINTER_UP://
mode = 0;
break;
default:
break;
}
imageView.setImageMatrix(matrix);
return true;
}
/**
* 得到两点之间的距离
*
* @param event
* @return
*/
private float distance(MotionEvent event) {
float dx = event.getX(1) - event.getX(0);
float dy = event.getY(1) - event.getY(0);
return FloatMath.sqrt(dx * dx + dy * dy);
}
/**
* 获取中心点
*
* @param event
* @return
*/
private PointF getMid(MotionEvent event) {
float dx = (event.getX(1) + event.getX(0)) / 2;
float dy = (event.getY(1) + event.getY(0)) / 2;
return new PointF(dx, dy);
}
}
}
关于Android Matrix的文章