Eine Touch-Geste wird ausgeführt, wenn ein Nutzer einen oder mehrere Finger auf den Touchscreen legt und Ihre App dieses Touch-Muster als Geste interpretiert. Die Bewegungserkennung erfolgt in zwei Phasen:
- Erfassung von Daten zu Berührungsereignissen
- Die Daten werden interpretiert, um festzustellen, ob sie die Kriterien für die von Ihrer App unterstützten Gesten erfüllen.
AndroidX-Klassen
In den Beispielen in diesem Dokument werden die Klassen GestureDetectorCompat und MotionEventCompat verwendet. Diese Klassen befinden sich in der AndroidX-Bibliothek. Verwenden Sie nach Möglichkeit AndroidX-Klassen, um die Kompatibilität mit älteren Geräten zu gewährleisten.
MotionEventCompat ist kein Ersatz für die Klasse MotionEvent. Stattdessen werden statische Hilfsmethoden bereitgestellt, an die Sie Ihr MotionEvent-Objekt übergeben, um die mit diesem Ereignis verknüpfte Aktion zu erhalten.
Datenauswertung
Wenn ein Nutzer einen oder mehrere Finger auf das Display legt, wird der Callback onTouchEvent() für die Ansicht ausgelöst, die die Touch-Ereignisse empfängt. Für jede Folge von Touch-Ereignissen, die als Geste erkannt wird, z. B. Position, Druck, Größe und Hinzufügen eines weiteren Fingers, wird onTouchEvent() mehrmals ausgelöst.
Die Geste beginnt, wenn der Nutzer den Bildschirm zum ersten Mal berührt, wird fortgesetzt, während das System die Position des Fingers oder der Finger des Nutzers verfolgt, und endet, wenn das letzte Ereignis erfasst wird, bei dem der letzte Finger des Nutzers den Bildschirm verlässt.
Während dieser Interaktion liefert die an onTouchEvent() übermittelte MotionEvent die Details jeder Interaktion. Ihre App kann die von MotionEvent bereitgestellten Daten verwenden, um zu ermitteln, ob eine für sie relevante Geste ausgeführt wird.
Berührungsereignisse für eine Aktivität oder Ansicht erfassen
Wenn Sie Berührungsereignisse in einem Activity oder View abfangen möchten, überschreiben Sie den onTouchEvent()-Callback.
Im folgenden Code-Snippet wird getAction() verwendet, um die Aktion, die der Nutzer aus dem Parameter event ausführt, zu extrahieren.
So erhalten Sie die Rohdaten, die Sie benötigen, um festzustellen, ob eine für Sie wichtige Geste ausgeführt wird.
Kotlin
class MainActivity : Activity() { ... // This example shows an Activity. You can use the same approach if you are // subclassing a View. override fun onTouchEvent(event: MotionEvent): Boolean { return when (event.action) { MotionEvent.ACTION_DOWN -> { Log.d(DEBUG_TAG, "Action was DOWN") true } MotionEvent.ACTION_MOVE -> { Log.d(DEBUG_TAG, "Action was MOVE") true } MotionEvent.ACTION_UP -> { Log.d(DEBUG_TAG, "Action was UP") true } MotionEvent.ACTION_CANCEL -> { Log.d(DEBUG_TAG, "Action was CANCEL") true } MotionEvent.ACTION_OUTSIDE -> { Log.d(DEBUG_TAG, "Movement occurred outside bounds of current screen element") true } else -> super.onTouchEvent(event) } } }
Java
public class MainActivity extends Activity { ... // This example shows an Activity. You can use the same approach if you are // subclassing a View. @Override public boolean onTouchEvent(MotionEvent event){ switch(event.getAction()) { case (MotionEvent.ACTION_DOWN) : Log.d(DEBUG_TAG,"Action was DOWN"); return true; case (MotionEvent.ACTION_MOVE) : Log.d(DEBUG_TAG,"Action was MOVE"); return true; case (MotionEvent.ACTION_UP) : Log.d(DEBUG_TAG,"Action was UP"); return true; case (MotionEvent.ACTION_CANCEL) : Log.d(DEBUG_TAG,"Action was CANCEL"); return true; case (MotionEvent.ACTION_OUTSIDE) : Log.d(DEBUG_TAG,"Movement occurred outside bounds of current screen element"); return true; default : return super.onTouchEvent(event); } }
Dieser Code erzeugt Meldungen wie die folgenden in Logcat, wenn der Nutzer tippt, berührt und hält und zieht:
GESTURES D Action was DOWN GESTURES D Action was UP GESTURES D Action was MOVE
Bei benutzerdefinierten Touch-Gesten können Sie diese Ereignisse dann selbst verarbeiten, um festzustellen, ob es sich um eine Geste handelt, die Sie verarbeiten müssen. Wenn Ihre App jedoch gängige Touchgesten wie Doppeltippen, Berühren und Halten oder Wischen verwendet, können Sie die Klasse GestureDetector nutzen. Mit GestureDetector können Sie häufige Gesten leichter erkennen, ohne die einzelnen Touch-Ereignisse selbst verarbeiten zu müssen. Weitere Informationen dazu finden Sie unter Gesten erkennen.
Berührungsereignisse für eine einzelne Ansicht erfassen
Alternativ zu onTouchEvent() können Sie ein View.OnTouchListener-Objekt mit der Methode setOnTouchListener() an ein beliebiges View-Objekt anhängen. So können Sie auf Berührungsereignisse reagieren, ohne eine vorhandene View zu unterteilen, wie im folgenden Beispiel gezeigt:
Kotlin
findViewById<View>(R.id.my_view).setOnTouchListener { v, event -> // Respond to touch events. true }
Java
View myView = findViewById(R.id.my_view); myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // Respond to touch events. return true; } });
Achten Sie darauf, keinen Listener zu erstellen, der false für das ACTION_DOWN-Ereignis zurückgibt.
In diesem Fall wird der Listener für die nachfolgende Sequenz von ACTION_MOVE- und ACTION_UP-Ereignissen nicht aufgerufen. Das liegt daran, dass ACTION_DOWN der Ausgangspunkt für alle Touch-Ereignisse ist.
Wenn Sie eine benutzerdefinierte Ansicht erstellen, können Sie onTouchEvent() überschreiben, wie oben beschrieben.
Gesten erkennen
Android bietet die Klasse GestureDetector zum Erkennen häufiger Gesten. Zu den unterstützten Gesten gehören onDown(), onLongPress() und onFling().
Sie können GestureDetector in Verbindung mit der oben beschriebenen Methode onTouchEvent() verwenden.
Alle unterstützten Gesten erkennen
Wenn Sie ein GestureDetectorCompat-Objekt instanziieren, ist einer der Parameter, die es akzeptiert, eine Klasse, die die GestureDetector.OnGestureListener-Schnittstelle implementiert. GestureDetector.OnGestureListener benachrichtigt Nutzer, wenn ein bestimmtes Touch-Ereignis eintritt. Damit Ihr GestureDetector-Objekt Ereignisse empfangen kann, überschreiben Sie die onTouchEvent()-Methode der Ansicht oder Aktivität und übergeben Sie alle beobachteten Ereignisse an die Detektorinstanz.
Im folgenden Snippet gibt ein Rückgabewert von true der einzelnen on<TouchEvent>-Methoden an, dass das Touch-Ereignis verarbeitet wird. Ein Rückgabewert von false leitet Ereignisse durch den View-Stack weiter, bis die Berührung erfolgreich verarbeitet wurde.
Wenn Sie das folgende Snippet in einer Test-App ausführen, können Sie nachvollziehen, wie Aktionen ausgelöst werden, wenn Sie mit dem Touchscreen interagieren, und was der Inhalt von MotionEvent für jedes Touch-Ereignis ist. Anschließend sehen Sie, wie viele Daten für einfache Interaktionen generiert werden.
Kotlin
private const val DEBUG_TAG = "Gestures" class MainActivity : Activity(), GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener { private lateinit var mDetector: GestureDetectorCompat // Called when the activity is first created. public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Instantiate the gesture detector with the // application context and an implementation of // GestureDetector.OnGestureListener. mDetector = GestureDetectorCompat(this, this) // Set the gesture detector as the double-tap // listener. mDetector.setOnDoubleTapListener(this) } override fun onTouchEvent(event: MotionEvent): Boolean { return if (mDetector.onTouchEvent(event)) { true } else { super.onTouchEvent(event) } } override fun onDown(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDown: $event") return true } override fun onFling( event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { Log.d(DEBUG_TAG, "onFling: $event1 $event2") return true } override fun onLongPress(event: MotionEvent) { Log.d(DEBUG_TAG, "onLongPress: $event") } override fun onScroll( event1: MotionEvent, event2: MotionEvent, distanceX: Float, distanceY: Float ): Boolean { Log.d(DEBUG_TAG, "onScroll: $event1 $event2") return true } override fun onShowPress(event: MotionEvent) { Log.d(DEBUG_TAG, "onShowPress: $event") } override fun onSingleTapUp(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onSingleTapUp: $event") return true } override fun onDoubleTap(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDoubleTap: $event") return true } override fun onDoubleTapEvent(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDoubleTapEvent: $event") return true } override fun onSingleTapConfirmed(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onSingleTapConfirmed: $event") return true } }
Java
public class MainActivity extends Activity implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{ private static final String DEBUG_TAG = "Gestures"; private GestureDetectorCompat mDetector; // Called when the activity is first created. @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Instantiate the gesture detector with the // application context and an implementation of // GestureDetector.OnGestureListener. mDetector = new GestureDetectorCompat(this,this); // Set the gesture detector as the double-tap // listener. mDetector.setOnDoubleTapListener(this); } @Override public boolean onTouchEvent(MotionEvent event){ if (this.mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString()); return true; } @Override public void onLongPress(MotionEvent event) { Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); } @Override public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) { Log.d(DEBUG_TAG, "onScroll: " + event1.toString() + event2.toString()); return true; } @Override public void onShowPress(MotionEvent event) { Log.d(DEBUG_TAG, "onShowPress: " + event.toString()); } @Override public boolean onSingleTapUp(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString()); return true; } @Override public boolean onDoubleTap(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); return true; } @Override public boolean onDoubleTapEvent(MotionEvent event) { Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString()); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent event) { Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); return true; } }
Eine Teilmenge der unterstützten Gesten erkennen
Wenn Sie nur wenige Gesten verarbeiten möchten, können Sie GestureDetector.SimpleOnGestureListener erweitern, anstatt die GestureDetector.OnGestureListener-Schnittstelle zu implementieren.
GestureDetector.SimpleOnGestureListener bietet eine Implementierung für alle on<TouchEvent>-Methoden, indem für alle false zurückgegeben wird. So können Sie nur die Methoden überschreiben, die Sie benötigen. Mit dem folgenden Code-Snippet wird beispielsweise eine Klasse erstellt, die GestureDetector.SimpleOnGestureListener erweitert und onFling() und onDown() überschreibt.
Unabhängig davon, ob Sie GestureDetector.OnGestureListener oder GestureDetector.SimpleOnGestureListener verwenden, ist es eine Best Practice, eine onDown()-Methode zu implementieren, die true zurückgibt. Das liegt daran, dass alle Gesten mit einer onDown()-Meldung beginnen. Wenn Sie false von onDown() zurückgeben, wie GestureDetector.SimpleOnGestureListener standardmäßig, geht das System davon aus, dass Sie den Rest der Touchgeste ignorieren möchten, und die anderen Methoden von GestureDetector.OnGestureListener werden nicht aufgerufen. Dies kann zu unerwarteten Problemen in Ihrer App führen. Geben Sie nur dann false von onDown() zurück, wenn Sie eine gesamte Geste wirklich ignorieren möchten.
Kotlin
private const val DEBUG_TAG = "Gestures" class MainActivity : Activity() { private lateinit var mDetector: GestureDetectorCompat public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mDetector = GestureDetectorCompat(this, MyGestureListener()) } override fun onTouchEvent(event: MotionEvent): Boolean { mDetector.onTouchEvent(event) return super.onTouchEvent(event) } private class MyGestureListener : GestureDetector.SimpleOnGestureListener() { override fun onDown(event: MotionEvent): Boolean { Log.d(DEBUG_TAG, "onDown: $event") return true } override fun onFling( event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { Log.d(DEBUG_TAG, "onFling: $event1 $event2") return true } } }
Java
public class MainActivity extends Activity { private GestureDetectorCompat mDetector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDetector = new GestureDetectorCompat(this, new MyGestureListener()); } @Override public boolean onTouchEvent(MotionEvent event){ if (this.mDetector.onTouchEvent(event)) { return true; } return super.onTouchEvent(event); } class MyGestureListener extends GestureDetector.SimpleOnGestureListener { private static final String DEBUG_TAG = "Gestures"; @Override public boolean onDown(MotionEvent event) { Log.d(DEBUG_TAG,"onDown: " + event.toString()); return true; } @Override public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString()); return true; } } }
Zusätzliche Ressourcen
- Übersicht über Eingabeereignisse
- Sensoren – Übersicht
- Benutzerdefinierte Ansicht interaktiv gestalten