[Android分享] 使用触摸手势(五)

来源:互联网 发布:表格文字识别软件 编辑:程序博客网 时间:2024/05/20 17:40
原文链接:http://developer.android.com/training/gestures/scale.html

拖动和缩放

拖动一个对象

触屏的常见操作是在屏幕上拖动一个对象。

1.在一个拖动操作中,应用程序需要保持对最初始点的跟踪,即使有其他的手指放置在屏幕上。例如,想象一下,当用户在屏幕上拖动图像,用户将第二个手指放在了屏幕上,并将第一个手指抬起。如果你的应用程序仅仅追踪单个点,那么它将会把第二个点作为目标位置并将图像移向那个位置。
2.为了阻止这种情况的发生,你的应用程序需要区分初始的点和后续的点。当后续的点按下或抬起时,ACTION_POINTER_DOWN和ACTION_POINTER_UP将会被传递到onTouchEvent()回调函数。
3.在ACTION_POINTER_UP的情况下,示例提取该触摸点的index,并确定该点ID有没有表示一个不再触摸屏幕的点。如果是这样,应用程序会选取一个不同的点进行激,并保存它的x和y坐标。由于这个保存的位置被用到ACTION_MOVE情况下来计算移动对象的距离,所以应用程序将使用正确的点计算移动的距离和位置。

下面的代码段能使用户在屏幕上拖动一个对象。它记录了初始点的位置,计算点移动的距离,并将对象移动到新的位置。它正确的处理了附加点的可能性。

你应该始终使用getActionMasked方法来获取一个MotionEvent的action。
?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// The ‘active pointer’ is the one currently moving our object.
privateint mActivePointerId = INVALID_POINTER_ID;
 
@Override
publicboolean onTouchEvent(MotionEvent ev) {
   // Let the ScaleGestureDetector inspect all events.
   mScaleDetector.onTouchEvent(ev);
              
   finalint action = MotionEventCompat.getActionMasked(ev);
         
   switch(action) {
   caseMotionEvent.ACTION_DOWN: {
        finalint pointerIndex = MotionEventCompat.getActionIndex(ev);
        finalfloat x = MotionEventCompat.getX(ev, pointerIndex);
        finalfloat y = MotionEventCompat.getY(ev, pointerIndex);
             
        // Remember where we started (for dragging)
        mLastTouchX = x;
        mLastTouchY = y;
        // Save the ID of this pointer (for dragging)
        mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
        break;
   }
             
   caseMotionEvent.ACTION_MOVE: {
        // Find the index of the active pointer and fetch its position
        finalint pointerIndex =
                MotionEventCompat.findPointerIndex(ev, mActivePointerId);  
             
        finalfloat x = MotionEventCompat.getX(ev, pointerIndex);
        finalfloat y = MotionEventCompat.getY(ev, pointerIndex);
             
        // Only move if the ScaleGestureDetector isn't processing a gesture.
        if(!mScaleDetector.isInProgress()) {
            // Calculate the distance moved
            finalfloat dx = x - mLastTouchX;
            finalfloat dy = y - mLastTouchY;
 
            mPosX += dx;
            mPosY += dy;
 
            invalidate();
        }
        // Remember this touch position for the next move event
        mLastTouchX = x;
        mLastTouchY = y;
 
        break;
   }
             
   caseMotionEvent.ACTION_UP: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
   }
             
   caseMotionEvent.ACTION_CANCEL: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
   }
         
   caseMotionEvent.ACTION_POINTER_UP: {
             
        finalint pointerIndex = MotionEventCompat.getActionIndex(ev);
        finalint pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
 
        if(pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            finalint newPointerIndex = pointerIndex == 0? 1: 0;
            mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
            mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
            mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
        }
        break;
   }
   }      
   returntrue;
}


使用触摸执行缩放

GestureDetector能够帮助你监听常见的手势。对于缩放,Android提供了ScaleGestureDetector. GestureDetector,ScaleGestureDetector能被用来检测更多的手势。

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
privateScaleGestureDetector mScaleDetector;
privatefloat mScaleFactor = 1.f;
 
publicMyCustomView(Context mContext){
   ...
   // View code goes here
   ...
   mScaleDetector = newScaleGestureDetector(context, newScaleListener());
}
 
@Override
publicboolean onTouchEvent(MotionEvent ev) {
   // Let the ScaleGestureDetector inspect all events.
   mScaleDetector.onTouchEvent(ev);
   returntrue;
}
 
@Override
publicvoid onDraw(Canvas canvas) {
   super.onDraw(canvas);
 
   canvas.save();
   canvas.scale(mScaleFactor, mScaleFactor);
   ...
   // onDraw() code goes here
   ...
   canvas.restore();
}
 
privateclass ScaleListener
        extendsScaleGestureDetector.SimpleOnScaleGestureListener {
   @Override
   publicboolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor();
 
        // Don't let the object get too small or too large.
        mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
 
        invalidate();
        returntrue;
   }
}