Android 處理多點(diǎn)觸控手勢(shì)

2018-08-02 18:21 更新

編寫:Andrwyw - 原文:http://developer.android.com/training/gestures/multi.html

多點(diǎn)觸控手勢(shì)是指在同一時(shí)間有多點(diǎn)(手指)觸碰屏幕。本節(jié)課程講述,如何檢測(cè)涉及多點(diǎn)的觸摸手勢(shì)。

追蹤多點(diǎn)

當(dāng)多個(gè)手指同時(shí)觸摸屏幕時(shí),系統(tǒng)會(huì)產(chǎn)生如下的觸摸事件:

  • ACTION_DOWN - 針對(duì)觸摸屏幕的第一個(gè)點(diǎn)。此事件是手勢(shì)的開(kāi)端。第一觸摸點(diǎn)的數(shù)據(jù)在MotionEvent中的索引總是0。
  • ACTION_POINTER_DOWN - 針對(duì)第一點(diǎn)后,出現(xiàn)在屏幕上額外的點(diǎn)。這個(gè)點(diǎn)的數(shù)據(jù)在MotionEvent中的索引,可以通過(guò)getActionIndex()獲得。
  • ACTION_MOVE - 在按下手勢(shì)期間發(fā)生變化。
  • ACTION_POINTER_UP - 當(dāng)非主要點(diǎn)(non-primary pointer)離開(kāi)屏幕時(shí),發(fā)送此事件。
  • ACTION_UP - 當(dāng)最后一點(diǎn)離開(kāi)屏幕時(shí)發(fā)送此事件。

我們可以通過(guò)各個(gè)點(diǎn)的索引以及id,單獨(dú)地追蹤MotionEvent中的每個(gè)點(diǎn)。

  • IndexMotionEvent把各個(gè)點(diǎn)的信息都存儲(chǔ)在一個(gè)數(shù)組中。點(diǎn)的索引值就是它在數(shù)組中的位置。大多數(shù)用來(lái)與點(diǎn)交互的MotionEvent函數(shù)都是以索引值而不是點(diǎn)的ID作為參數(shù)的。
  • ID:每個(gè)點(diǎn)也都有一個(gè)ID映射,該ID映射在整個(gè)手勢(shì)期間一直存在,以便我們單獨(dú)地追蹤每個(gè)點(diǎn)。

每個(gè)獨(dú)立的點(diǎn)在移動(dòng)事件中出現(xiàn)的次序是不固定的。因此,從一個(gè)事件到另一個(gè)事件,點(diǎn)的索引值是可以改變的,但點(diǎn)的ID在它的生命周期內(nèi)是保證不會(huì)改變的。使用getPointerId()可以獲得一個(gè)點(diǎn)的ID,在手勢(shì)隨后的移動(dòng)事件中,就可以用該ID來(lái)追蹤這個(gè)點(diǎn)。對(duì)于隨后一系列的事件,可以使用findPointerIndex()函數(shù),來(lái)獲得對(duì)應(yīng)給定ID的點(diǎn)在移動(dòng)事件中的索引值。如下:

private int mActivePointerId;

public boolean onTouchEvent(MotionEvent event) {
    ....
    // Get the pointer ID
    mActivePointerId = event.getPointerId(0);

    // ... Many touch events later...

    // Use the pointer ID to find the index of the active pointer
    // and fetch its position
    int pointerIndex = event.findPointerIndex(mActivePointerId);
    // Get the pointer's current position
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);
}

獲取MotionEvent的動(dòng)作

我們應(yīng)該總是使用getActionMasked()函數(shù)(或者用MotionEventCompat.getActionMasked()這個(gè)兼容版本更好)來(lái)獲取MotionEvent的動(dòng)作(action)。與舊的getAction()函數(shù)不同的是,getActionMasked()是設(shè)計(jì)用來(lái)處理多點(diǎn)觸摸的。它會(huì)返回執(zhí)行過(guò)的動(dòng)作的掩碼值,不包括點(diǎn)的索引位。然后,我們可以使用getActionIndex()來(lái)獲得與該動(dòng)作關(guān)聯(lián)的點(diǎn)的索引值。這在接下來(lái)的代碼段中可以看到。

Note: 這個(gè)樣例使用的是MotionEventCompat類。該類在Support Library中。我們應(yīng)該使用MotionEventCompat類,來(lái)提供對(duì)更多平臺(tái)的支持。需要注意的一點(diǎn)是,MotionEventCompat并不是MotionEvent類的替代品。準(zhǔn)確來(lái)說(shuō),它提供了一些靜態(tài)工具類函數(shù),我們可以把MotionEvent對(duì)象作為參數(shù)傳遞給這些函數(shù),來(lái)得到與事件相關(guān)的動(dòng)作。

int action = MotionEventCompat.getActionMasked(event);
// Get the index of the pointer associated with the action.
int index = MotionEventCompat.getActionIndex(event);
int xPos = -1;
int yPos = -1;

Log.d(DEBUG_TAG,"The action is " + actionToString(action));

if (event.getPointerCount() > 1) {
    Log.d(DEBUG_TAG,"Multitouch event");
    // The coordinates of the current screen contact, relative to
    // the responding View or Activity.
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);

} else {
    // Single touch event
    Log.d(DEBUG_TAG,"Single touch event");
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);
}
...

// Given an action int, returns a string description
public static String actionToString(int action) {
    switch (action) {

        case MotionEvent.ACTION_DOWN: return "Down";
        case MotionEvent.ACTION_MOVE: return "Move";
        case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down";
        case MotionEvent.ACTION_UP: return "Up";
        case MotionEvent.ACTION_POINTER_UP: return "Pointer Up";
        case MotionEvent.ACTION_OUTSIDE: return "Outside";
        case MotionEvent.ACTION_CANCEL: return "Cancel";
    }
    return "";
}

關(guān)于多點(diǎn)觸摸的更多內(nèi)容以及示例,可以查看拖拽與縮放章節(jié)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)