现在的位置: 首页 > 综合 > 正文

android资料–Android通过手势(多点)缩放和拖拽图片

2013年10月09日 ⁄ 综合 ⁄ 共 6130字 ⁄ 字号 评论关闭

在MotionEvent中有两个事件值得注意一下,分别是ACTION_DOWN和ACTION_POINTER_DOWN。
ACTION_DOWN:这个很好理解,当屏幕检测到有手指按下之后就触发到这个事件。
ACTION_POINTER_DOWN:这个是实现多点的关键,当屏幕检测到有多个手指同时按下之后,就触发了这个事件。
通过getAction()可以获得当前屏幕的事件类型:ACTION_DOWN, ACTION_MOVE, ACTION_UP, or ACTION_CANCEL。但是如果像获得如上的ACTION_POINTER_DOWN,则得和ACTION_MASK相与才能得到ACTION_POINTER_DOWN事件。
所以我们运用一个switch-case结构就可以实现对图片进行拖拽或缩放,而缩放的只要思想是在移动的过程中计算两个点之间的距离,然后再进行缩放。

多点触摸是可以的,还是用OnTouchListener。
单点触摸取得坐标的时候一般都用event.getX()和event.getY()。
其实还有一组方法,
event.getX(int pointerIndex)和event.getY(int pointerIndex),
看参数就知道怎么用了吧。
在onTouch(View v, MotionEvent event)的里面,
switch (event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
//单点模式
case MotionEvent.ACTION_POINTER_DOWN:
//计算当前点和前一个DOWN点之间的距离,超过一定范围可以认为是多点模式
case MotionEvent.ACTION_MOVE:
//多点模式时,计算两点距离,通过与第一次的计算值的比例,得到缩放比例
//单点模式时,计算移动距离,设置LayoutParams
case MotionEvent.ACTION_POINTER_UP:
//重置掉多点模式和记录的距离等等
case MotionEvent.ACTION_UP:
//处理单点模式,计算移动距离,设置LayoutParams
}

      上代码:

  1.        @Override
  2.         public boolean onTouch(View v, MotionEvent event) {
  3.                 ImageView view = (ImageView) v;
  4.                 dumpEvent(event);
  5.                 // Handle touch events here...
  6.                 switch (event.getAction() & MotionEvent.ACTION_MASK) {
  7.                 case MotionEvent.ACTION_DOWN:
  8.                         matrix.set(view.getImageMatrix());
  9.                         savedMatrix.set(matrix);
  10.                         start.set(event.getX(), event.getY());
  11.                         //Log.d(TAG, "mode=DRAG");
  12.                         mode = DRAG;
  13.                         //Log.d(TAG, "mode=NONE");
  14.                         break;
  15.                 case MotionEvent.ACTION_POINTER_DOWN:
  16.                         oldDist = spacing(event);
  17.                         //Log.d(TAG, "oldDist=" + oldDist);
  18.                         if (oldDist > 10f) {
  19.                                 savedMatrix.set(matrix);
  20.                                 midPoint(mid, event);
  21.                                 mode = ZOOM;
  22.                                 //Log.d(TAG, "mode=ZOOM");
  23.                         }// ACTION_DOWN, ACTION_MOVE, ACTION_UP, or ACTION_CANCEL.
  24.                         break;
  25.                 case MotionEvent.ACTION_UP:
  26.                 case MotionEvent.ACTION_POINTER_UP:
  27.                         mode = NONE;
  28.                         break;
  29.                 case MotionEvent.ACTION_MOVE:
  30.                         if (mode == DRAG) {
  31.                                 // ...
  32.                                 matrix.set(savedMatrix);
  33.                                 matrix.postTranslate(event.getX() - start.x, event.getY()
  34.                                                 - start.y);
  35.                         } else if (mode == ZOOM) {
  36.                                 float newDist = spacing(event);
  37.                                 //Log.d(TAG, "newDist=" + newDist);
  38.                                 if (newDist > 10f) {
  39.                                         matrix.set(savedMatrix);
  40.                                         float scale = newDist / oldDist;
  41.                                         matrix.postScale(scale, scale, mid.x, mid.y);
  42.                                 }
  43.                         }
  44.                         break;
  45.                 }
  46.                 view.setImageMatrix(matrix);
  47.                 return true; // indicate event was handled
  48.         }
  49.         private void dumpEvent(MotionEvent event) {
  50.                 String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
  51.                                 "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
  52.                 StringBuilder sb = new StringBuilder();
  53.                 int action = event.getAction();
  54.                 int actionCode = action & MotionEvent.ACTION_MASK;
  55.                 sb.append("event ACTION_").append(names[actionCode]);
  56.                 if (actionCode == MotionEvent.ACTION_POINTER_DOWN
  57.                                 || actionCode == MotionEvent.ACTION_POINTER_UP) {
  58.                         sb.append("(pid ").append(
  59.                                         action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
  60.                         sb.append(")");
  61.                 }
  62.                 sb.append("[");
  63.                 for (int i = 0; i < event.getPointerCount(); i++) {
  64.                         sb.append("#").append(i);
  65.                         sb.append("(pid ").append(event.getPointerId(i));
  66.                         sb.append(")=").append((int) event.getX(i));
  67.                         sb.append(",").append((int) event.getY(i));
  68.                         if (i + 1 < event.getPointerCount())
  69.                                 sb.append(";");
  70.                 }
  71.                 sb.append("]");
  72.                 //Log.d(TAG, sb.toString());
  73.         }

复制代码

求两点间距离:

  1. private float spacing(MotionEvent event) {
  2.                 float x = event.getX(0) - event.getX(1);
  3.                 float y = event.getY(0) - event.getY(1);
  4.                 return FloatMath.sqrt(x * x + y * y);
  5.         }

求两点间中点:

  1.         private void midPoint(PointF point, MotionEvent event) {
  2.                 float x = event.getX(0) + event.getX(1);
  3.                 float y = event.getY(0) + event.getY(1);
  4.                 point.set(x/2, y/2);
  5.         }

 

 

 

额外参考资料(英文):
     Android thinks about touch events in terms of gestures. A gesture in this sense includes all events from the first finger that touches the screen to the last finger that leaves the screen. A single gesture's entire event sequence is
always sent to the same view that was picked during the initial ACTION_DOWN unless a parent intercepts the event stream for some reason. If a parent intercepts a child's event stream, the child will get ACTION_CANCEL.
     If you're working with multitouch events, always use the value returned by getActionMasked() to determine the action. If you don't need multitouch or are working with an older platform version, you can ignore the ACTION_POINTER_* events.
     ACTION_DOWN is for the first finger that touches the screen. This starts the gesture. The pointer data for this finger is always at index 0 in the MotionEvent.
     ACTION_POINTER_DOWN is for extra fingers that enter the screen beyond the first. The pointer data for this finger is at the index returned by getActionIndex().
     ACTION_POINTER_UP is sent when a finger leaves the screen but at least one finger is still touching it. The last data sample about the finger that went up is at the index returned by getActionIndex().
     ACTION_UP is sent when the last finger leaves the screen. The last data sample about the finger that went up is at index 0. This ends the gesture.
ACTION_CANCEL means the entire gesture was aborted for some reason. This ends the gesture.

 

 

   

抱歉!评论已关闭.