2016-09-19 16 views
5

Mam problem z moją aplikacją na Androida, która wymaga zdarzeń śledzenia dotyku (śledzenie kiedy/gdzie palec schodzi, porusza się, up itd.). Muszę używać funkcji event.getX() i event.getY(), aby uzyskać współrzędne bieżącego dotyku.Android MotionEvent Wskaźnik indeksu Confusion

Więc z czego się nauczyłem w ciągu ostatnich kilku miesięcy:

  • MotionEvent.ACTION_DOWN śledzi pierwszy lądować
  • MotionEvent.ACTION_POINTER_DOWN utwory późniejsze dotyka
  • MotionEvent.ACTION_UP śledzi ostatnie podciąć
  • MotionEvent.ACTION_POINTER_UP utwory dotykowe, które się podnoszą
  • MotionEvent.ACTION_MOVE śledzi każdy ruch dotykowy

W mojej aplikacji napotykam na znaczący problem, gdy mój pierwszy dotyk idzie w górę. Powiedzmy, że mam pięć palców dotykających mojego urządzenia (możemy wywołać te Dotyk 0, 1, 2, 3, 4). Teraz, kiedy podniosłem Touch 0, MotionEvent.ACTION_POINTER_UP to akcja, którą otrzymuję. Całkowicie zrozumiałe; Rozumiem. Jednak teraz te dwie rzeczy się wydarzy:

  • Przenieś nic z Touches 1-4: Otrzymaj IllegalArgumentException mówi mi pointerIndex jest poza zakresem
  • Podnieś coś z Touches 1-4: Spits powrotem informacje dla inna touch (event.getX() i event.getY() da mi różne informacje palec)

Jestem trochę na końcu mojego dowcip o tym, jak poprawnie zapisuje te informacje. Jakieś wskazówki dotyczące prawidłowego śledzenia informacji lub kompensowania wskaźników dotykowych?

Podałem ogólny układ mojego kodu, ale czuję, że nie robię nic nadzwyczajnego (i jestem pewien, że jest on bliski przykładowemu kodowi na przykładach Androida?):

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    int action = event.getActionMasked(); 
    int ptr_idx = event.getPointerId(event.getActionIndex()); 

    try { 
     switch (action) { 
      case MotionEvent.ACTION_MOVE: 
       handleActionPointerMove(event); 
       break; 

      // Order of touch downs doesn't matter to us 
      case MotionEvent.ACTION_DOWN: 
      case MotionEvent.ACTION_POINTER_DOWN: 
       handleActionPointerDown(event, ptr_idx); 
       break; 

      case MotionEvent.ACTION_UP: 
      case MotionEvent.ACTION_POINTER_UP: 
       handleActionPointerUp(event, ptr_idx); 
       break; 
      } 
     } 
     catch (IllegalArgumentException e) { 
      e.printStackTrace(); 
      return false; 
     } 

     return true; 
    } 
} 

public void handleActionPointerMove(MotionEvent event) { 
    for (int i = 0; i < event.getPointerCount(); i++) { 
     handleInformation(event.getX(i), event.getY(i)); 
    } 
} 

public void handleActionPointerDown(MotionEvent event, int ptr_idx) { 
    handleInformation(event.getX(ptr_idx), event.getY(ptr_idx)); 
} 

public void handleActionPointerUp(MotionEvent event, int ptr_idx) { 
    handleInformation(event.getX(ptr_idx), event.getY(ptr_idx)); 
} 

public void handleInformation(int x, int y) { 
    // Figures out what x+y means to us (are we in a certain box within the app? outside in clear zones? etc 
} 

Odpowiedz

0

Dobrze po myślenia o nim na noc stałam go do pracy robi to przed wywołaniem MotionEvent.getX() i MotionEvent.getY():

public int getAdjustment(int ptr_idx) { 
    int adjust = 0; 
    for (int i = 0; i < event.getPointerCount(); i++) { 
     // Get Actual Pointer Index of touch 
     int adjustedPointerIndex = event.getPointerId(i); 
     // If we've found the current touch's pointer index AND 
     // the pointer index doesn't equal the sequential event's 
     // pointers 
     if ((adjustPointerIndex == ptr_idx) && (i != adjustPointerIndex)) { 
      adjust = (adjustPointerIndex - i); 
      break; 
     } 
    } 

    return adjust; 
} 

// Example Function using getAdjustment(int ptr_idx) 
public void handleActionPointerUp(MotionEvent event, int ptr_idx) { 
    int adjustment = ptr_idx - getAdjustment(ptr_idx); 
    handleInformation(event.getX(adjustment), event.getY(adjustment)); 
} 

wyjaśnienie dla instrukcji pętli:

Zasadniczo powiedzmy, że mamy 4 dotknięcia (dotknij 0, 1, 2, 3). Teraz podnieśliśmy Touch 0, a teraz mamy Touch 1, 2, 3. Android zobaczy te dotknięcia jako 0, 1, 2 i rzeczywiste wskaźniki wskaźnika jako 1, 2, 3. Aby uzyskać poprawną korektę, przechodzę do iteracji wskaźniki MotionEvent (obecnie jest to 0, 1, 2 w pętli for).

Teraz, jeśli z jakiegoś powodu zostanie wyzerowane dotknięcie 0 lub dowolny dotyk, musimy dostosować indeks wskaźnika jako getX(), a getY() nie rozumie indeksu wskaźnika dotykowego. Przyjmuje tylko indeksy 0, 1, 2, mimo że mamy indeksy wskaźników 1, 2, 3. Tak więc, jeśli osiągnęliśmy właściwy bieżący indeks wskaźnika dotykowego, ALE indeks dotykowy MotionEvent nie jest równy indeksowi wskaźnika dotykowego, dostosowujemy go, wykonując adjust = adjustPointerIndex-i.

Po wykonaniu tej czynności, po prostu odjąć go od obecnego ptr_idx jesteśmy analizuj i otrzymujemy wartość getX() i getY() można zrozumieć bez IllegalArgumentException dla pointerIndex poza zasięgiem.

Wyjaśnię dokładniej, jeśli to nie ma sensu i jeśli ktoś ma bardziej eleganckie rozwiązanie, proszę dać mi znać, ponieważ jestem pewien, że nie jest to świetny sposób, aby sobie z tym poradzić. Wolę oznaczać cudzą odpowiedź jako zatwierdzoną odpowiedź.