Bei einer Multi-Touch-Geste tippen mehrere Zeiger (Finger) gleichzeitig auf den Bildschirm. In diesem Dokument wird beschrieben, wie Gesten mit mehreren Zeigern erkannt werden.
Mehrere Cursor verfolgen
Wenn mehrere Zeiger gleichzeitig auf den Bildschirm tippen, generiert das System die folgenden Touch-Ereignisse:
ACTION_DOWN
: wird gesendet, wenn der erste Zeiger auf den Bildschirm tippt. Dadurch wird die Geste gestartet. Die Zeigerdaten für diesen Zeiger befinden sich immer am Index0
inMotionEvent
.ACTION_POINTER_DOWN
: wird gesendet, wenn zusätzliche Zeiger nach dem ersten auf dem Bildschirm erscheinen. MitgetActionIndex()
können Sie den Index des Zeigers abrufen, der gerade ausgefallen ist.ACTION_MOVE
: wird gesendet, wenn eine Änderung in einer Geste mit einer beliebigen Anzahl von Zeigern erfolgt.ACTION_POINTER_UP
: wird gesendet, wenn ein nicht primärer Zeiger nach oben bewegt wird. Sie können den Index des gerade gestiegenen Zeigers mitgetActionIndex()
abrufen.ACTION_UP
: wird gesendet, wenn der letzte Mauszeiger den Bildschirm verlässt.ACTION_CANCEL
: Gibt an, dass die gesamte Geste einschließlich aller Zeiger abgebrochen wurde.
Touch-Gesten zum Starten und Beenden
Eine Geste besteht aus einer Reihe von Ereignissen, die mit einem ACTION_DOWN
-Ereignis beginnen und mit einem ACTION_UP
- oder ACTION_CANCEL
-Ereignis enden. Es ist immer nur eine Bewegung aktiv. Die Aktionen UNTEN, VERSCHIEBEN, NACH OBEN und ABBRECHEN gelten für die gesamte Geste. Ein Ereignis mit ACTION_MOVE
kann beispielsweise eine Bewegung für alle Zeiger nach unten zu diesem Zeitpunkt anzeigen.
Zeiger im Blick behalten
Verwenden Sie den Index und die ID des Zeigers, um die einzelnen Zeigerpositionen innerhalb einer MotionEvent
zu verfolgen.
- Index: Ein
MotionEvent
speichert Zeigerinformationen in einem Array. Der Index eines Zeigers ist seine Position innerhalb dieses Arrays. Die meistenMotionEvent
-Methoden verwenden den Zeigerindex anstelle der Zeiger-ID als Parameter. - ID: Jeder Zeiger hat auch eine ID-Zuordnung, die über Touch-Ereignisse hinweg dauerhaft bleibt, um einen einzelnen Zeiger über die gesamte Geste hinweg zu verfolgen.
Einzelne Zeiger erscheinen in einer nicht definierten Reihenfolge innerhalb eines Bewegungsereignisses. Somit kann sich der Index eines Zeigers von einem Ereignis zum nächsten ändern. Die Zeiger-ID eines Zeigers bleibt jedoch garantiert konstant, solange er aktiv ist. Mit der Methode getPointerId()
rufen Sie die Zeiger-ID ab, um den Zeiger bei allen nachfolgenden Bewegungsereignissen in einer Geste zu verfolgen. Verwenden Sie dann für aufeinanderfolgende Bewegungsereignisse die Methode findPointerIndex()
, um den Zeigerindex für eine bestimmte Zeiger-ID in diesem Bewegungsereignis abzurufen.
Beispiel:
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); ... }
Damit mehrere Touchpointer unterstützt werden, kannst du alle aktiven Cursor mit ihren IDs zu ihren jeweiligen ACTION_POINTER_DOWN
- und ACTION_DOWN
-Ereignissen im Cache speichern. Entfernen Sie die Cursor bei den ACTION_POINTER_UP
- und ACTION_UP
-Ereignissen aus dem Cache. Diese im Cache gespeicherten IDs könnten für die Verarbeitung anderer Aktionsereignisse hilfreich sein. Wenn Sie beispielsweise ein ACTION_MOVE
-Ereignis verarbeiten, müssen Sie den Index für jede im Cache gespeicherte aktive Zeiger-ID ermitteln, die Koordinaten des Zeigers mit den Funktionen getX()
und getY()
abrufen und diese Koordinaten dann mit den im Cache gespeicherten Koordinaten vergleichen, um festzustellen, welche Zeiger sich bewegt haben.
Verwenden Sie die Funktion getActionIndex()
nur mit den Ereignissen ACTION_POINTER_UP
und ACTION_POINTER_DOWN
. Verwenden Sie diese Funktion nicht mit ACTION_MOVE
-Ereignissen, da sie immer 0
zurückgibt.
MotionEvent
Aktionen abrufen
Verwenden Sie die Methode getActionMasked()
oder die Kompatibilitätsversion MotionEventCompat.getActionMasked()
, um die Aktion einer MotionEvent
abzurufen. Im Gegensatz zur vorherigen Methode getAction()
ist getActionMasked()
so konzipiert, dass es mit mehreren Verweisen funktioniert. Sie gibt die Aktion ohne die Zeigerindizes zurück. Verwenden Sie für Aktionen mit einem gültigen Zeigerindex getActionIndex()
, um den Index der mit der Aktion verknüpften Zeiger zurückzugeben, wie im folgenden Snippet gezeigt:
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 ""; }
Zusätzliche Ressourcen
Weitere Informationen zu Eingabeereignissen finden Sie in den folgenden Referenzen:
- Eingabeereignisse – Übersicht
- Sensoren – Übersicht
- Benutzerdefinierte Ansicht interaktiv gestalten
- Ziehen und skalieren