2013-01-18 40 views
3

我一直在一個遊戲中工作,我試圖讓控制器,沒有太複雜,爲此我需要跟蹤2個輸入(手指):1火按鈕和移動鍵(上,下,左,右)你如何使用MotionEvent.ACTION_POINTER_INDEX_SHIFT?

這就是問題:手指1向下,手指2下來,手指1上升想這是2,然後手指2上升想這是1

D/Controlls(18849): Action Down 1 
D/Controlls(18849): Coordinates 267.7908 415.24274 
D/Controlls(18849): Action Pointer Down 2 
D/Controlls(18849): Coordinates 281.11423 417.23993 
D/Controlls(18849): Action Pointer UP 1 
D/Controlls(18849): Coordinates 272.7869 419.23718 
D/Controlls(18849): Action UP 2 
D/Controlls(18849): Coordinates 1148.103 439.20947 

這是用於處理2個輸入的OnTouchEvent的代碼:

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    int index = event.getActionIndex(); 
    int pointerId = event.getPointerId(index); 
    int action = event.getActionMasked(); 

    int oldX, oldY; 

    switch (event.getAction() & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: 
     { 
      hero.moveControlls((int)event.getX(), (int)event.getY()); 
      Log.d("Controlls", "Action Down "+ pointerId); 
      Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY()); 
      break; 
     } 

     case MotionEvent.ACTION_UP: 
     { 
      hero.setScreenTouching(false); 
      Log.d("Controlls", "Action UP "+ pointerId); 
      Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY()); 
      break; 
     } 

     case MotionEvent.ACTION_POINTER_DOWN: 
     { 
      Log.d("Controlls", "Action Pointer Down "+ pointerId); 
      Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY());     
      break; 
     } 

     case MotionEvent.ACTION_POINTER_UP: 
     { 
      Log.d("Controlls", "Action Pointer UP "+ pointerId); 
      Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY()); 
      break; 
     } 
    } 
    return true; 
} 

現在,我擡頭看了一些例子,但無法理解它們。我在API中查找了MotionEvent,它說使用$ ACTION_POINTER_INDEX_SHIFT $,我不知道如何使用它,因爲它們沒有示例或使它更容易理解。任何幫助如何做到這一點?

回答

2

我認爲混亂可以是方法getX()getY()總是返回指針(第一/只有一個向下)的座標。因此,您的日誌手指1中的前三個事件是主要的,然後在最後,即使只剩下手指2,它也成爲主要事件。

如果要正確跟蹤兩個手指的事件,則需要使用getX(int)getY(int);將指針索引作爲參數的版本,因此您可以分散地獲取每個事件中每個手指的座標。請注意,如果每個手指的指數按照不同的順序向下和向上,則指數可能會發生變化,但是給定的手指始終具有相同的指針ID。

一個好方法是檢查每個事件中指針的數量(例如getPointerCount())。用一個手指,索引0是有效的;用兩個手指,索引0和1是有效的。獲取每個有效指針的座標,然後使用getPointerId()來確定每個座標對應匹配哪個手指。

編輯

給您張貼到返回的座標爲右指針的源代碼最簡單的修改是將索引添加到二級指針參數,就像這樣:

int index = event.getActionIndex(); 
int pointerId = event.getPointerId(index); 
int action = event.getActionMasked(); 

int oldX, oldY; 

switch (event.getActionMasked()) { 
    case MotionEvent.ACTION_DOWN: 
    { 
     hero.moveControlls((int)event.getX(), (int)event.getY()); 
     Log.d("Controlls", "Action Down " + pointerId); 
     Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY()); 
     break; 
    } 

    case MotionEvent.ACTION_UP: 
    { 
     hero.setScreenTouching(false); 
     Log.d("Controlls", "Action UP "+ pointerId); 
     Log.d("Controlls", "Coordinates "+ event.getX() + " "+ event.getY()); 
     break; 
    } 

    case MotionEvent.ACTION_POINTER_DOWN: 
    { 
     Log.d("Controlls", "Action Pointer Down "+ pointerId); 
     Log.d("Controlls", "Coordinates "+ event.getX(index) + " "+ event.getY(index)); 
     break; 
    } 

    case MotionEvent.ACTION_POINTER_UP: 
    { 
     Log.d("Controlls", "Action Pointer UP "+ pointerId); 
     Log.d("Controlls", "Coordinates "+ event.getX(index) + " "+ event.getY(index)); 
     break; 
    } 
} 

這應該使數據更符合您期望看到的內容。

+0

我有點得到你在說什麼,但仍然不能實現你介意給我一個例子嗎? –

+0

我修改了你的switch語句。 – Devunwired

+0

我有一些類似的問題。您介意說明使用MotionEvent.ACTION_POINTER_INDEX_MASK(在每個關於此主題的示例中都會發生)對動作進行「與」操作以及該轉換的目的是什麼?我也不清楚這些面具是什麼,文件是神祕的。我會非常感謝,併爲更清晰地upvote。謝謝! – Rookatu

10

無論何時輔助指針停機或啓動,都會觸發ACTION_POINTER_DOWN和ACTION_POINTER_UP。如果屏幕上已經有一個指針並且新的指針熄滅,則您將收到ACTION_POINTER_DOWN而不是ACTION_DOWN。如果指針上升但至少仍有一個觸摸屏幕,您將收到ACTION_POINTER_UP而不是ACTION_UP。

ACTION_POINTER_DOWN和ACTION_POINTER_UP事件對操作值中的額外信息進行編碼。取與它MotionEvent.ACTION_MASK給我們的行動不變,而取與它ACTION_POINTER_INDEX_MASK給我們的指針或漲跌互現

以提取左觸摸傳感器的指針的指數最好的辦法索引。

int pointerIndex =(event。getAction()& MotionEvent.ACTION_POINTER_INDEX_MASK)>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;

我會相應地改變你的代碼如下圖所示:如果您在不同的順序釋放的指針不是按(使用多點觸控什麼時候可偏偏)

case MotionEvent.ACTION_POINTER_UP: 
{ 
    int index = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
    int pointId = event.getPointerId(index); 
    Log.d("Controlls", "Action Pointer UP "+ pointerId); 
    Log.d("Controlls", "Coordinates "+ event.getX(index) + " "+ event.getY(index)); 
    break; 
} 
+0

真棒。謝謝袁! –

+1

使用MotionEventCompat.getActionIndex有點乾淨 – Delyan

0

上面的代碼可能會失敗。我發現下面的代碼工作的3個指針並按下然後釋放的順序並不重要:

case MotionEvent.ACTION_UP: // for single touch 
    case MotionEvent.ACTION_POINTER_UP: // when order of touch and release is the same 
    case MotionEvent.ACTION_POINTER_UP + ((1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT)): // for any order of two pointers 
    case MotionEvent.ACTION_POINTER_UP + ((2 << MotionEvent.ACTION_POINTER_INDEX_SHIFT)): // for any order of three pointers 
    case MotionEvent.ACTION_OUTSIDE: // when moving touch out of the view 
    case MotionEvent.ACTION_CANCEL: // when canceling touch (eg by home button) 
    // some code to support releasing pointers 
    break; 

記住,旁邊情況聲明必須是一個恆定值,因此基於價值無法計算event.getMotion()