Eine Touch-Geste wird ausgelöst, wenn ein Nutzer einen oder mehrere Finger auf den Touchscreen setzt und Ihre App dieses Berührungsmuster als Geste interpretiert. Die Gestenerkennung erfolgt in zwei Phasen:
- Touch-Ereignisdaten werden erfasst.
- Interpretieren der Daten, 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 für Kompatibilität mit früheren Geräten zu sorgen.
MotionEventCompat
ist kein Ersatz für die Klasse MotionEvent
. Stattdessen werden statische Dienstprogrammmethoden bereitgestellt, an die das MotionEvent
-Objekt übergeben wird, um die mit diesem Ereignis verknüpfte Aktion zu empfangen.
Datenauswertung
Wenn ein Nutzer einen oder mehrere Finger auf den Bildschirm setzt, wird der Callback onTouchEvent()
in der Ansicht ausgelöst, die die Touch-Ereignisse empfängt. Für jede als Geste erkannte Sequenz von Touch-Ereignissen wie Position, Druck, Größe und Hinzufügung eines weiteren Fingers wird onTouchEvent()
mehrmals ausgelöst.
Die Geste beginnt, wenn der Nutzer das erste Mal den Bildschirm berührt, wird fortgesetzt, während das System die Position des Fingers oder der Finger des Nutzers erfasst, und endet mit der Erfassung des letzten Ereignisses, in dem der letzte Finger den Bildschirm verlässt.
Während dieser Interaktion liefert das an onTouchEvent()
gesendete MotionEvent
die Details jeder Interaktion. Ihre App kann die von MotionEvent
bereitgestellten Daten verwenden, um zu bestimmen, ob eine für sie wichtige Geste ausgeführt wird.
Berührungsereignisse für eine Aktivität oder Ansicht erfassen
Wenn Touchereignisse in einem Activity
oder View
erfasst werden sollen, überschreibe den onTouchEvent()
-Callback.
Im folgenden Code-Snippet wird mit getAction()
die Aktion extrahiert, die der Nutzer aus dem Parameter event
ausführt.
Auf diese Weise erhalten Sie die erforderlichen Rohdaten, 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 in Logcat folgende Meldungen, wenn der Nutzer tippt, hält und zieht:
GESTURES D Action was DOWN GESTURES D Action was UP GESTURES D Action was MOVE
Bei benutzerdefinierten Gesten können Sie diese Ereignisse dann selbst verarbeiten, um festzustellen, ob sie eine Geste darstellen, die Sie verarbeiten müssen. Wenn Ihre App jedoch gängige Touch-Gesten wie Doppeltippen, Berühren und Halten, Wischen usw. verwendet, können Sie die Klasse GestureDetector
nutzen. Mit GestureDetector
können Sie häufige Touch-Gesten einfacher erkennen, ohne die einzelnen Touch-Ereignisse selbst zu verarbeiten. Weitere Informationen hierzu finden Sie unter Gesten erkennen.
Touch-Ereignisse in einer Ansicht erfassen
Alternativ zu onTouchEvent()
können Sie mit der Methode setOnTouchListener()
ein View.OnTouchListener
-Objekt an ein beliebiges View
-Objekt anhängen. So ist es möglich, auf Touch-Ereignisse zu warten, ohne einem vorhandenen View
abgeleitet zu werden, 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; } });
Sie sollten Vorsicht walten lassen, wenn Sie einen Listener erstellen, der false
für das ACTION_DOWN
-Ereignis zurückgibt.
In diesem Fall wird der Listener für die nachfolgende ACTION_MOVE
- und ACTION_UP
-Ereignissequenz 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()
wie oben beschrieben überschreiben.
Touch-Gesten erkennen
Android bietet die Klasse GestureDetector
für die Erkennung gängiger Touch-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 Touch-Gesten erkennen
Wenn Sie ein GestureDetectorCompat
-Objekt instanziieren, wird unter anderem eine Klasse verwendet, die die GestureDetector.OnGestureListener
-Schnittstelle implementiert. GestureDetector.OnGestureListener
benachrichtigt Nutzer, wenn ein bestimmtes Berührungsereignis eintritt. Damit das GestureDetector
-Objekt Ereignisse empfangen kann, müssen Sie die onTouchEvent()
-Methode der Ansicht oder Aktivität überschreiben und alle beobachteten Ereignisse an die Detektorinstanz übergeben.
Im folgenden Snippet gibt ein Rückgabewert von true
aus den einzelnen on<TouchEvent>
-Methoden an, dass das Touch-Ereignis verarbeitet wird. Ein Rückgabewert von false
übergibt Ereignisse über den Ansichtsstapel, bis die Berührung erfolgreich verarbeitet wurde.
Wenn Sie das folgende Snippet in einer Test-App ausführen, können Sie sich einen Eindruck davon verschaffen, wie Aktionen ausgelöst werden, wenn Sie mit dem Touchscreen interagieren, und wie der Inhalt von MotionEvent
für jedes Touch-Ereignis ist. Sie sehen dann, 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 Touch-Gesten erkennen
Wenn Sie nur wenige Touch-Gesten verarbeiten möchten, können Sie GestureDetector.SimpleOnGestureListener
erweitern, statt die GestureDetector.OnGestureListener
-Schnittstelle zu implementieren.
GestureDetector.SimpleOnGestureListener
ermöglicht eine Implementierung aller on<TouchEvent>
-Methoden. Dazu wird false
für alle Methoden zurückgegeben. So können Sie nur die Methoden überschreiben, die für Sie wichtig sind. 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, empfiehlt es sich, eine onDown()
-Methode zu implementieren, die true
zurückgibt. Das liegt daran, dass alle Touch-Gesten mit einer onDown()
-Nachricht beginnen. Wenn Sie false
von onDown()
zurückgeben, wie es GestureDetector.SimpleOnGestureListener
standardmäßig tut, geht das System davon aus, dass Sie den Rest der Geste ignorieren möchten. Die anderen Methoden von GestureDetector.OnGestureListener
werden nicht aufgerufen. Dies kann zu unerwarteten Problemen in Ihrer App führen. Geben Sie false
nur dann von onDown()
zurück, wenn Sie wirklich eine ganze Geste 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; } } }