Si verifica un gesto multi-touch quando più puntatori (dita) toccano lo schermo contemporaneamente. Questo documento descrive come rilevare i gesti che coinvolgono più puntatori.
Traccia più puntatori
Quando più puntatori toccano lo schermo contemporaneamente, il sistema genera i seguenti eventi touch:
ACTION_DOWN
: viene inviata quando il primo puntatore tocca lo schermo. Questa azione avvia il gesto. I dati del puntatore per questo puntatore si trovano sempre nell'indice0
inMotionEvent
.ACTION_POINTER_DOWN
: inviato quando puntatori aggiuntivi entrano nello schermo dopo il primo. Puoi ottenere l'indice del puntatore appena diminuito utilizzandogetActionIndex()
.ACTION_MOVE
: viene inviata quando si verifica una modifica in un gesto, che coinvolge un numero qualsiasi di puntatori.ACTION_POINTER_UP
: viene inviato quando un puntatore non principale sale verso l'alto. Puoi ottenere l'indice del puntatore appena aumentato utilizzandogetActionIndex()
.ACTION_UP
: viene inviato quando l'ultimo puntatore si allontana dallo schermo.ACTION_CANCEL
: indica che l'intero gesto, inclusi tutti i puntatori, viene annullato.
Gesti di inizio e fine
Un gesto è una serie di eventi che inizia con un evento ACTION_DOWN
e termina con un evento ACTION_UP
o ACTION_CANCEL
. È presente un gesto attivo alla volta. Le azioni GIÙ, SPOSTA, SU e ANNULLA si applicano all'intero gesto. Ad esempio, un evento con ACTION_MOVE
può indicare un movimento per tutti i puntatori verso il basso in un determinato momento.
Tieni traccia dei puntatori
Utilizza l'indice e l'ID del puntatore per tenere traccia delle singole posizioni dei puntatori all'interno di un elemento MotionEvent
.
- Indice: un elemento
MotionEvent
memorizza le informazioni di puntamento in un array. L'indice di un puntatore è la sua posizione all'interno di questo array. La maggior parte dei metodiMotionEvent
prende l'indice del puntatore come parametro, anziché l'ID del puntatore. - ID: ogni puntatore ha anche una mappatura degli ID che rimane permanente tra gli eventi di tocco per consentire il monitoraggio di un singolo puntatore durante l'intero gesto.
I singoli puntatori vengono visualizzati all'interno di un evento di movimento in un ordine non definito. Pertanto,
l'indice di un puntatore può cambiare da un evento a quello successivo, ma l'ID del puntatore di un puntatore rimane costante finché
il puntatore rimane attivo. Utilizza il metodo getPointerId()
per ottenere l'ID di un puntatore per tenere traccia del puntatore in tutti gli eventi di movimento successivi di un gesto. Quindi, per gli eventi di movimento successivi, usa il metodo findPointerIndex()
per ottenere l'indice del puntatore per un determinato ID puntatore nell'evento di movimento.
Ecco alcuni esempi:
Kotlin
private var mActivePointerId: Int = 0 override fun onTouchEvent(event: MotionEvent): Boolean { ... // 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. val (x: Float, y: Float) = event.findPointerIndex(mActivePointerId).let { pointerIndex -> // Get the pointer's current position. event.getX(pointerIndex) to event.getY(pointerIndex) } ... }
Java
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); ... }
Per supportare più puntatori touch, puoi memorizzare nella cache tutti i puntatori attivi con i relativi ID in corrispondenza dei singoli puntatori ACTION_POINTER_DOWN
e ACTION_DOWN
. Rimuovi i puntatori dalla cache in corrispondenza degli eventi ACTION_POINTER_UP
e ACTION_UP
. Potresti trovare utili questi ID memorizzati nella cache per gestire correttamente altri eventi di azione. Ad esempio, durante l'elaborazione di un evento ACTION_MOVE
, trova l'indice di ogni ID puntatore attivo memorizzato nella cache, recupera le coordinate del puntatore utilizzando le funzioni getX()
e getY()
, quindi confronta queste coordinate con quelle memorizzate nella cache per scoprire quali puntatori sono stati spostati.
Utilizza la funzione getActionIndex()
solo con gli eventi ACTION_POINTER_UP
e ACTION_POINTER_DOWN
. Non utilizzare questa funzione con gli eventi ACTION_MOVE
, in quanto restituisce sempre 0
.
Recupera MotionEvent
azioni
Utilizza il
metodo getActionMasked()
o la versione di compatibilità
MotionEventCompat.getActionMasked()
per recuperare l'azione di un MotionEvent
. A differenza del metodo getAction()
precedente, getActionMasked()
è progettato per funzionare con più puntatori. Restituisce l'azione senza gli indici del puntatore. Per le azioni con un
indice di puntatore valido, utilizza getActionIndex()
per restituire l'indice
dei puntatori associati all'azione, come mostrato nello snippet seguente:
Kotlin
val (xPos: Int, yPos: Int) = MotionEventCompat.getActionMasked(event).let { action -> Log.d(DEBUG_TAG, "The action is ${actionToString(action)}") // Get the index of the pointer associated with the action. MotionEventCompat.getActionIndex(event).let { index -> // The coordinates of the current screen contact, relative to // the responding View or Activity. MotionEventCompat.getX(event, index).toInt() to MotionEventCompat.getY(event, index).toInt() } } if (event.pointerCount > 1) { Log.d(DEBUG_TAG, "Multitouch event") } else { // Single touch event. Log.d(DEBUG_TAG, "Single touch event") } ... // Given an action int, returns a string description. fun actionToString(action: Int): String { return when (action) { MotionEvent.ACTION_DOWN -> "Down" MotionEvent.ACTION_MOVE -> "Move" MotionEvent.ACTION_POINTER_DOWN -> "Pointer Down" MotionEvent.ACTION_UP -> "Up" MotionEvent.ACTION_POINTER_UP -> "Pointer Up" MotionEvent.ACTION_OUTSIDE -> "Outside" MotionEvent.ACTION_CANCEL -> "Cancel" else -> "" } }
Java
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 ""; }
Risorse aggiuntive
Per ulteriori informazioni relative agli eventi di input, consulta i seguenti riferimenti:
- Panoramica degli eventi di input
- Panoramica dei sensori
- Rendere una visualizzazione personalizzata interattiva
- Trascinamento e scala