android 多点触控
在android中多指触控通过OnTouchListener监听器监听,触控事件在onTouch方法中分析处理。
在单指触控中,我们常用的三个方法ACTION_DOWN、ACTION_UP、ACTION_MOVE,在多指触控中也会用到,不过用法稍有不同。
多指触控中多了ACTION_POINTER_DOWN、ACTION_POINTER_UP两种情况,这几个情况的触发用法在下面源码中标注:
switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: //第一根手指按下时触发 mode = 1; break; case MotionEvent.ACTION_POINTER_DOWN: //第二根或以上的手指按下时触发 mode += 1; break; case MotionEvent.ACTION_UP: //所有手指都离开时触发 mode = 0; break; case MotionEvent.ACTION_POINTER_UP: //当有两根及以上手指触碰屏幕,其一离开时触发 mode -= 1; break; case MotionEvent.ACTION_MOVE: //此事件非常灵敏,只要有手指触碰屏幕,便会一直触发 if (mode >= 2) { } break; }
触碰的手指数可用event.getPointerCount()方法获取。
放大缩小:
此功能可通过手指之间的前后距离倍数来确定放大缩小的倍数,不这样稍微麻烦了点,我们可以用ScaleGestureDetector来实现:
scaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.OnScaleGestureListener() { @Override public boolean onScale(ScaleGestureDetector detector) { float factor = detector.getScaleFactor(); float x = detector.getFocusX(); float y = detector.getFocusY(); Show.log("onScale:" + factor + ";" + x + ";" + y); matrix.postScale(factor, factor, x, y); iv.setImageMatrix(matrix); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { Show.log("onScaleBegin"); return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { Show.log("onScaleEnd"); } }); iv = (ImageView) findViewById(R.id.img_test); iv.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) {\ scaleGestureDetector.onTouchEvent(event); return true; } });
多指滑动:
先获取各点的中点,而后根据中点的位移来进行判断,下面是一个简单样例:
public class MainActivity extends Activity { private ImageView iv; Matrix matrix = new Matrix(); private PointF startPoint; private PointF nowPoint; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startPoint = new PointF(); nowPoint = new PointF(); iv = (ImageView) findViewById(R.id.img_test); iv.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: setEventPoint(event,startPoint); break; case MotionEvent.ACTION_MOVE: setEventPoint(event,nowPoint); Show.log("move:"+getDistance(startPoint,nowPoint)); matrix.postTranslate(nowPoint.x-startPoint.x,nowPoint.y-startPoint.y); startPoint.set(nowPoint.x,nowPoint.y); break; case MotionEvent.ACTION_UP: setEventPoint(event,nowPoint); Show.log("end:"+getDistance(startPoint,nowPoint)); break; } iv.setImageMatrix(matrix); return true; } }); } private void setEventPoint(MotionEvent event, PointF startPoint) { float x = 0, y = 0; final int pointerCount = event.getPointerCount(); for (int i = 0; i < pointerCount; i++) { x += event.getX(i); y += event.getY(i); } x = x / pointerCount; y = y / pointerCount; startPoint.set(x,y); } private float getDistance(PointF point1,PointF point2){ float x = point1.x-point2.x; float y = point1.y-point2.y; return (float) Math.sqrt(x * x + y * y); } }