Un gesto multitocco si verifica quando più puntatori (dita) toccano lo schermo contemporaneamente. Questo documento descrive come rilevare i gesti che coinvolgono più puntatori.
Monitorare più puntatori
Quando più puntatori toccano lo schermo contemporaneamente, il sistema genera i seguenti eventi di tocco:
ACTION_DOWN: inviato quando il primo puntatore tocca lo schermo. Inizia il gesto. I dati del puntatore per questo puntatore si trovano sempre all'indice0inMotionEvent.ACTION_POINTER_DOWN: inviato quando sullo schermo entrano puntatori aggiuntivi dopo il primo. Puoi ottenere l'indice del puntatore appena abbassato utilizzandogetActionIndex().ACTION_MOVE: inviato quando si verifica una modifica in un gesto, che coinvolge un numero qualsiasi di puntatori.ACTION_POINTER_UP: inviato quando un puntatore non primario viene sollevato. Puoi ottenere l'indice del puntatore appena aumentato utilizzandogetActionIndex().ACTION_UP: inviato quando l'ultimo puntatore lascia lo schermo.ACTION_CANCEL: indica che l'intera sequenza di tasti, inclusi tutti i puntatori, viene annullata.
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. C'è un solo gesto attivo alla volta. Le azioni
DOWN, MOVE, UP e CANCEL si applicano all'intera sequenza di tasti. Ad esempio, un
evento con ACTION_MOVE può indicare un movimento di tutti i puntatori
verso il basso in quel momento.
Tenere traccia dei puntatori
Utilizza l'indice e l'ID del puntatore per tenere traccia delle posizioni dei singoli puntatori all'interno di un MotionEvent.
- Indice: un puntatore a
MotionEventnegozi informazioni in un array. L'indice di un puntatore è la sua posizione all'interno di questo array. La maggior parte dei metodiMotionEventaccetta l'indice del puntatore come parametro, anziché l'ID puntatore. - ID: ogni puntatore ha anche una mappatura dell'ID che rimane persistente tra gli eventi tocco per consentire il monitoraggio di un singolo puntatore durante l'intera sequenza di tasti.
I singoli indicatori 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 all'altro, ma l'ID puntatore
di un puntatore è garantito che rimanga costante finché il puntatore rimane
attivo. Utilizza il metodo
getPointerId()
per ottenere l'ID di un puntatore e monitorarlo in tutti gli eventi di movimento successivi di un gesto. Poi, per gli eventi di movimento successivi, utilizza il metodo
findPointerIndex()
per ottenere l'indice del puntatore per un determinato ID puntatore in quell'evento di movimento.
Ad esempio:
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 tocco, puoi memorizzare nella cache tutti i puntatori attivi con
i relativi ID al momento dell'evento ACTION_POINTER_DOWN e
ACTION_DOWN. Rimuovi i puntatori dalla cache in corrispondenza
degli eventi ACTION_POINTER_UP e ACTION_UP. Questi ID memorizzati nella cache potrebbero esserti utili per gestire correttamente altri eventi di azione. Ad esempio, quando elabori un evento ACTION_MOVE, trova l'indice per 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 si sono 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, poiché
restituisce sempre 0.
Recuperare le azioni di MotionEvent
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 del puntatore valido, utilizza getActionIndex() per restituire l'indice dei
puntatori associati all'azione, come mostrato nel seguente snippet:
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 maggiori informazioni sugli eventi di input, consulta i seguenti riferimenti:
- Panoramica degli eventi di input
- Panoramica dei sensori
- Rendere interattiva una visualizzazione personalizzata
- Trascina e ridimensiona