1.创建接受并处理View中onTouchEvent的类MultiTouchImpl,在其构造方法中需要传入监听接口,在MultiTouchImpl类中创建一个public方法onTouchEvent来接收View中传递过来的触摸事件
写onTouchEvent方法:
ACTION为ACTION_POINTER_DOWN时(表示第二次按下):1.记录按下的两个点 2.计算缩放锚点 3.计算两点之间距离 4.抛出监听的抽象方法
ACTION为ACTION_POINTER_UP时(表示第一次抬起):1.记录抬起时的点2.判断是否发生最终缩放3.若发生缩放,则抛出监听的抽象方法,否则return false
ACTION为ACTION_MOVE时:1.记录move的点2.计算两点之间距离,并与距离的初始值进行比较,计算出缩放比例,3.抛出监听的抽象方法
import android.graphics.PointF;
import android.graphics.RectF;
import android.view.MotionEvent;
// MultiTouchImpl.java
// 实现多点触摸缩放功能
public class MultiTouchImpl {
enum MULTI_TOUCH_MODE {
DRAG_ON, DRAG_OFF
}
public final static int MAX_TOUCH_POINTS = 2;
MULTI_TOUCH_MODE mode = MULTI_TOUCH_MODE.DRAG_OFF;
private PointF mTouchDownPoint0; // 按下触摸屏的位置
private PointF mTouchDownPoint1; // 按下触摸屏的位置
PointF pt0;
PointF pt1;
float oldDist = 1f;
private IMultiTouch listener = null;
private float mStartDistance;
private PointF mBeginPt;
public MultiTouchImpl(IMultiTouch context) {
listener = context;
mBeginPt = new PointF();
mTouchDownPoint0 = new PointF();
mTouchDownPoint1 = new PointF();
pt0 = new PointF();
pt1 = new PointF();
}
public boolean onTouchEvent(MotionEvent event) {
int touchPoints = event.getPointerCount();
if (touchPoints != 2) {
return true;
}
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
mode = MULTI_TOUCH_MODE.DRAG_ON;
mBeginPt.set((event.getX(1) + event.getX(0)) / 2,
(event.getY(1) + event.getY(0)) / 2);
mStartDistance = getDistance(event.getX(0), event.getY(0),
event.getX(1), event.getY(1));
mTouchDownPoint0.set(event.getX(0), event.getY(0));
mTouchDownPoint1.set(event.getX(1), event.getY(1));
listener.OnDragBegin();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = MULTI_TOUCH_MODE.DRAG_OFF;
pt0.set(event.getX(0), event.getY(0));
pt1.set(event.getX(1), event.getY(1));
if (!this.isPointMove(pt0, mTouchDownPoint0)
&& !this.isPointMove(pt1, mTouchDownPoint1)) {
// 发送右键
return false;
} else {
listener.OnDragEnd();
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == MULTI_TOUCH_MODE.DRAG_ON) {
pt0.set(event.getX(0), event.getY(0));
pt1.set(event.getX(1), event.getY(1));
if (this.isPointMove(pt0, mTouchDownPoint0)
|| this.isPointMove(pt1, mTouchDownPoint1)) {
float distance = getDistance(event.getX(0), event.getY(0),
event.getX(1), event.getY(1));
float scale = 1;
if (mStartDistance != 0)
scale = distance / mStartDistance;
PointF cur = new PointF(
(event.getX(1) + event.getX(0)) / 2,
(event.getY(1) + event.getY(0)) / 2);
listener.OnDraging(mBeginPt, cur, scale);
}
}
break;
}
return true;
}
public IMultiTouch setListener(IMultiTouch l) {
IMultiTouch ret = listener;
listener = l;
return ret;
}
private float getDistance(float x1, float y1, float x2, float y2) {
float dx = (x2 - x1);
float dy = (y2 - y1);
return (float) Math.sqrt((dx * dx + dy * dy));
}
private boolean isPointMove(PointF pt, PointF touchPoint) {
float w = 60.0f;
RectF rc = new RectF();
rc.set(touchPoint.x - w / 2, touchPoint.y - w / 2,
touchPoint.x + w / 2, touchPoint.y + w / 2);
return !rc.contains(pt.x, pt.y);
}
}
2.创建监听接口:
接口中定义三个抽象方法OnDragBegin(),OnDraging(PointF begin, PointF end, float mScale),OnDragEnd()
import android.graphics.PointF;
import android.graphics.PointF;
/**
* @author Q
*
*/
public interface IMultiTouch {
/**
* 当缩放手势开始时回调
*/
public abstract void OnDragBegin();
/**
* 当缩放手势正在发生时回调, after OnDragBegin(), before OnDragEnd.
*
* @param begin
* 缩放手势发生时两手批中心点坐标.
* @param end
* 当前事件(Move)发生时两手指中心点的坐标.
* @param mScale
* 当前事件发生时两手指距离/手势开始时两手指的距离.
*/
public abstract void OnDraging(PointF begin, PointF end, float mScale);
/**
* 当缩放手势结束时回调
*/
public abstract void OnDragEnd();
}
3.在自定义View中创建MultiTouchImpl对象,并实现监听接口,在其中的onTouchEvent中,使用MultiTouchImpl的onTouchEvent方法来处理触摸事件。
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean bRetCode = true;
bRetCode = mMultiTouchImpl.onTouchEvent(event);
return bRetCode;
}