Eine Multi-Touch-Geste liegt vor, wenn mehrere Zeiger (Finger) gleichzeitig auf den Bildschirm tippen. In diesem Dokument wird beschrieben, wie Gesten erkannt werden, die mehrere Zeiger umfassen.
Mehrere Hinweise erfassen
Wenn mehrere Zeiger gleichzeitig auf den Bildschirm tippen, generiert das System die folgenden Touch-Ereignisse:
ACTION_DOWN
: wird gesendet, wenn der erste Mauszeiger auf den Bildschirm tippt. Dadurch wird die Touch-Geste gestartet. Die Zeigerdaten für diesen Zeiger befinden sich immer bei Index0
inMotionEvent
.ACTION_POINTER_DOWN
: wird gesendet, wenn nach dem ersten zusätzlichen Mauszeiger auf dem Bildschirm erscheint. Sie können den Index des gerade gesunkenen Zeigers mitgetActionIndex()
abrufen.ACTION_MOVE
: wird gesendet, wenn bei einer Geste eine Änderung vorgenommen wird. Dabei kann eine beliebige Anzahl von Zeigern verwendet werden.ACTION_POINTER_UP
: wird gesendet, wenn ein nicht-primärer Cursor nach oben steigt. Sie können den Index des Zeigers, der gerade nach oben gestiegen ist, mitgetActionIndex()
abrufen.ACTION_UP
: Wird gesendet, wenn der letzte Mauszeiger den Bildschirm verlässt.ACTION_CANCEL
: Gibt an, dass die gesamte Touch-Geste einschließlich aller Mauszeiger abgebrochen wird.
Start- und End-Touch-Gesten
Eine Geste ist eine Reihe von Ereignissen, die mit einem ACTION_DOWN
-Ereignis beginnen und mit einem ACTION_UP
- oder ACTION_CANCEL
-Ereignis endet. Es gibt jeweils eine aktive Geste. 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 anzeigen.
Zeiger im Blick behalten
Verwenden Sie den Index und die ID des Zeigers, um die einzelnen Zeigerpositionen innerhalb eines 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 als Parameter und nicht als Zeiger-ID. - ID: Jeder Zeiger verfügt außerdem über eine ID-Zuordnung, die über Touchereignisse hinweg dauerhaft bleibt, um die Verfolgung eines einzelnen Zeigers über die gesamte Geste zu ermöglichen.
Einzelne Zeiger werden innerhalb eines Bewegungsereignisses in einer nicht definierten Reihenfolge angezeigt. Daher kann sich der Index eines Zeigers von einem Ereignis zum nächsten ändern. Die Zeiger-ID eines Zeigers bleibt jedoch garantiert konstant, solange der Zeiger aktiv bleibt. Verwenden Sie die Methode getPointerId()
, um die ID eines Zeigers abzurufen und ihn über alle nachfolgenden Bewegungsereignisse 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); ... }
Zur Unterstützung mehrerer Touchpointer können Sie alle aktiven Cursor mit ihren IDs zu ihrem jeweiligen ACTION_POINTER_DOWN
- und ACTION_DOWN
-Ereigniszeitpunkt im Cache speichern. Entfernen Sie die Zeiger an den zugehörigen ACTION_POINTER_UP
- und ACTION_UP
-Ereignissen aus dem Cache. Diese im Cache gespeicherten IDs können hilfreich sein, um andere Aktionsereignisse korrekt zu verarbeiten. Wenn Sie beispielsweise ein ACTION_MOVE
-Ereignis verarbeiten, können Sie den Index für jede im Cache gespeicherte aktive Zeiger-ID ermitteln, die Koordinaten des Zeigers mithilfe der Funktionen getX()
und getY()
abrufen und diese Koordinaten dann mit den im Cache gespeicherten Koordinaten vergleichen, um festzustellen, welche Zeiger verschoben wurden.
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 eines MotionEvent
abzurufen. Im Gegensatz zur vorherigen getAction()
-Methode ist getActionMasked()
für mehrere Zeiger konzipiert. Sie gibt die Aktion ohne Zeigerindexe 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 ""; }
Weitere Informationen
Weitere Informationen zu Eingabeereignissen finden Sie in den folgenden Referenzen:
- Eingabeereignisse – Übersicht
- Sensoren – Übersicht
- Benutzerdefinierte Ansicht interaktiv machen
- Ziehen und skalieren