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

本文介绍如何在Android应用中实现对象的拖动与缩放功能。通过追踪触摸点并处理多点触摸事件,确保拖动操作流畅进行。同时利用ScaleGestureDetector检测缩放手势,调整对象大小。
原文链接: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.
private int mActivePointerId = INVALID_POINTER_ID;
 
@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);
              
    final int action = MotionEventCompat.getActionMasked(ev);
         
    switch (action) {
    case MotionEvent.ACTION_DOWN: {
         final int pointerIndex = MotionEventCompat.getActionIndex(ev);
         final float x = MotionEventCompat.getX(ev, pointerIndex);
         final float 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 ;
    }
             
    case MotionEvent.ACTION_MOVE: {
         // Find the index of the active pointer and fetch its position
         final int pointerIndex =
                MotionEventCompat.findPointerIndex(ev, mActivePointerId);  
             
         final float x = MotionEventCompat.getX(ev, pointerIndex);
         final float y = MotionEventCompat.getY(ev, pointerIndex);
             
         // Only move if the ScaleGestureDetector isn't processing a gesture.
         if (!mScaleDetector.isInProgress()) {
             // Calculate the distance moved
             final float dx = x - mLastTouchX;
             final float dy = y - mLastTouchY;
 
             mPosX += dx;
             mPosY += dy;
 
             invalidate();
         }
         // Remember this touch position for the next move event
         mLastTouchX = x;
         mLastTouchY = y;
 
         break ;
    }
             
    case MotionEvent.ACTION_UP: {
         mActivePointerId = INVALID_POINTER_ID;
         break ;
    }
             
    case MotionEvent.ACTION_CANCEL: {
         mActivePointerId = INVALID_POINTER_ID;
         break ;
    }
         
    case MotionEvent.ACTION_POINTER_UP: {
             
         final int pointerIndex = MotionEventCompat.getActionIndex(ev);
         final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
 
         if (pointerId == mActivePointerId) {
             // This was our active pointer going up. Choose a new
             // active pointer and adjust accordingly.
             final int newPointerIndex = pointerIndex == 0 ? 1 : 0 ;
             mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
             mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
             mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
         }
         break ;
    }
    }      
    return true ;
}


使用触摸执行缩放

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
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1 .f;
 
public MyCustomView(Context mContext){
    ...
    // View code goes here
    ...
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
 
@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Let the ScaleGestureDetector inspect all events.
    mScaleDetector.onTouchEvent(ev);
    return true ;
}
 
@Override
public void onDraw(Canvas canvas) {
    super .onDraw(canvas);
 
    canvas.save();
    canvas.scale(mScaleFactor, mScaleFactor);
    ...
    // onDraw() code goes here
    ...
    canvas.restore();
}
 
private class ScaleListener
         extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean 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();
         return true ;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值