In dieser Lektion wird beschrieben, wie Bewegungen bei Berührungsereignissen erfasst werden.
Ein neues onTouchEvent()
wird mit einem ACTION_MOVE
-Ereignis ausgelöst, wenn sich die aktuelle Position, der Druck oder die Größe des Kontaktkontakts ändert. Wie unter Häufige Touch-Gesten erkennen beschrieben, werden alle diese Ereignisse im Parameter MotionEvent
von onTouchEvent()
aufgezeichnet.
Da fingerbasiertes Berühren nicht immer die genaueste Form der Interaktion ist, basiert die Erkennung von Berührungsereignissen oft mehr auf Bewegung als auf einem einfachen Kontakt. Damit Apps zwischen bewegungsbasierten Gesten (z. B. Wischen) und bewegungsfreien Gesten (z. B. einmaliges Tippen) unterscheiden können, umfasst Android das Konzept Touch Slop. Touch Slop bezieht sich auf den Abstand in Pixeln, den ein Nutzer bei einer Berührung bewegen kann, bevor die Geste als bewegungsbasierte Geste interpretiert wird. Weitere Informationen zu diesem Thema finden Sie unter Touch-Ereignisse in einer ViewGroup verwalten.
Je nach den Anforderungen Ihrer App gibt es mehrere Möglichkeiten, Bewegungen in einer Geste zu verfolgen. Beispiele:
- Die Start- und Endposition eines Zeigers, z. B. das Verschieben eines Objekts auf dem Bildschirm von Punkt A zu Punkt B.
- Die Richtung, in die sich der Zeiger bewegt, wie durch die X- und Y-Koordinaten bestimmt.
- Verlauf. Die Größe des Verlaufs einer Touch-Geste können Sie über die Methode
MotionEvent
getHistorySize()
abrufen. Anschließend können Sie mithilfe dergetHistorical<Value>
-Methoden des Bewegungsereignisses Position, Größe, Zeit und Druck der einzelnen historischen Ereignisse abrufen. Der Verlauf ist nützlich, wenn eine Spur des Fingers des Nutzers gerendert wird, z. B. beim Zeichnen per Berührung. Weitere Informationen finden Sie in derMotionEvent
-Referenz. - Die Geschwindigkeit des Zeigers, wenn er sich über den Touchscreen bewegt.
Weitere Informationen finden Sie in den folgenden Ressourcen:
Geschwindigkeit verfolgen
Sie können eine bewegungsbasierte Geste einrichten, die auf der Entfernung oder Richtung basiert, die der Zeiger zurücklegt. Die Geschwindigkeit ist jedoch häufig ein ausschlaggebender Faktor für die Verfolgung der Eigenschaften einer Geste oder die Entscheidung, ob die Geste erfolgt ist. Android bietet die Klasse VelocityTracker
, um die Berechnung der Geschwindigkeit zu vereinfachen.
VelocityTracker
hilft dir, die Geschwindigkeit von Berührungsereignissen zu verfolgen. Dies ist nützlich bei Gesten, bei denen die Geschwindigkeit Teil des Kriteriums für die Geste ist, z. B. ein Ziehen.
Das folgende Beispiel veranschaulicht den Zweck der Methoden in der VelocityTracker
API:
Kotlin
private const val DEBUG_TAG = "Velocity" class MainActivity : Activity() { private var mVelocityTracker: VelocityTracker? = null override fun onTouchEvent(event: MotionEvent): Boolean { when (event.actionMasked) { MotionEvent.ACTION_DOWN -> { // Reset the velocity tracker back to its initial state. mVelocityTracker?.clear() // If necessary, retrieve a new VelocityTracker object to watch // the velocity of a motion. mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain() // Add a user's movement to the tracker. mVelocityTracker?.addMovement(event) } MotionEvent.ACTION_MOVE -> { mVelocityTracker?.apply { val pointerId: Int = event.getPointerId(event.actionIndex) addMovement(event) // When you want to determine the velocity, call // computeCurrentVelocity(). Then, call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer // ID. computeCurrentVelocity(1000) // Log velocity of pixels per second. It's best practice to // use VelocityTrackerCompat where possible. Log.d("", "X velocity: ${getXVelocity(pointerId)}") Log.d("", "Y velocity: ${getYVelocity(pointerId)}") } } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // Return a VelocityTracker object back to be re-used by others. mVelocityTracker?.recycle() mVelocityTracker = null } } return true } }
Java
public class MainActivity extends Activity { private static final String DEBUG_TAG = "Velocity"; ... private VelocityTracker mVelocityTracker = null; @Override public boolean onTouchEvent(MotionEvent event) { int index = event.getActionIndex(); int action = event.getActionMasked(); int pointerId = event.getPointerId(index); switch(action) { case MotionEvent.ACTION_DOWN: if(mVelocityTracker == null) { // Retrieve a new VelocityTracker object to watch the // velocity of a motion. mVelocityTracker = VelocityTracker.obtain(); } else { // Reset the velocity tracker back to its initial state. mVelocityTracker.clear(); } // Add a user's movement to the tracker. mVelocityTracker.addMovement(event); break; case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); // When you want to determine the velocity, call // computeCurrentVelocity(). Then call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer ID. mVelocityTracker.computeCurrentVelocity(1000); // Log velocity of pixels per second. It's best practice to use // VelocityTrackerCompat where possible. Log.d("", "X velocity: " + mVelocityTracker.getXVelocity(pointerId)); Log.d("", "Y velocity: " + mVelocityTracker.getYVelocity(pointerId)); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // Return a VelocityTracker object back to be re-used by others. mVelocityTracker.recycle(); break; } return true; } }
Pointer Capture verwenden
Einige Anwendungen wie Spiele, Remote-Desktop- und Virtualisierungsclients profitieren von der Kontrolle über den Mauszeiger. Die Zeigererfassung ist eine in Android 8.0 (API-Level 26) und höher verfügbare Funktion, die dieses Steuerelement bietet, indem alle Mausereignisse in einer fokussierten Ansicht in Ihrer App ausgeliefert werden.
Zeigererfassung anfordern
Eine Ansicht in Ihrer Anwendung kann nur dann die Zeigererfassung anfordern, wenn die Ansichtshierarchie, in der sie enthalten ist, im Fokus ist. Aus diesem Grund sollte die Anfragezeigererfassung erfolgen, wenn eine bestimmte Nutzeraktion in der Ansicht erfolgt, z. B. während eines onClick()
-Ereignisses oder im onWindowFocusChanged()
-Event-Handler Ihrer Aktivität.
Wenn Sie eine Zeigererfassung anfordern möchten, rufen Sie die Methode requestPointerCapture()
für die Ansicht auf. Das folgende Codebeispiel zeigt, wie Sie die Zeigererfassung anfordern, wenn der Nutzer auf eine Ansicht klickt:
Kotlin
fun onClick(view: View) { view.requestPointerCapture() }
Java
@Override public void onClick(View view) { view.requestPointerCapture(); }
Wenn die Anfrage zum Erfassen des Zeigers erfolgreich ist, ruft Android onPointerCaptureChange(true)
auf.
Das System liefert die Mausereignisse an die fokussierte Ansicht in Ihrer App, solange sie sich in derselben Ansichtshierarchie wie die Ansicht befindet, die die Erfassung angefordert hat. Andere Apps empfangen keine Mausereignisse mehr, bis die Erfassung freigegeben wird, einschließlich ACTION_OUTSIDE
-Ereignissen. Android liefert Zeigerereignisse von anderen Quellen als der Maus ganz normal, aber der Mauszeiger ist nicht mehr sichtbar.
Erfasste Zeigerereignisse verarbeiten
Sobald eine Ansicht die Zeigererfassung erfolgreich erfasst hat, löst Android die Mausereignisse aus. In der fokussierten Ansicht können Sie die Ereignisse verarbeiten, indem Sie eine der folgenden Aufgaben ausführen:
- Wenn Sie eine benutzerdefinierte Ansicht verwenden, überschreiben Sie
onCapturedPointerEvent(MotionEvent)
. - Registrieren Sie andernfalls ein
OnCapturedPointerListener
.
Das folgende Codebeispiel zeigt, wie onCapturedPointerEvent(MotionEvent)
implementiert wird:
Kotlin
override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean { // Get the coordinates required by your app. val verticalOffset: Float = motionEvent.y // Use the coordinates to update your view and return true if the event is // successfully processed. return true }
Java
@Override public boolean onCapturedPointerEvent(MotionEvent motionEvent) { // Get the coordinates required by your app. float verticalOffset = motionEvent.getY(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; }
Das folgende Codebeispiel zeigt, wie ein OnCapturedPointerListener
registriert wird:
Kotlin
myView.setOnCapturedPointerListener { view, motionEvent -> // Get the coordinates required by your app. val horizontalOffset: Float = motionEvent.x // Use the coordinates to update your view and return true if the event is // successfully processed. true }
Java
myView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() { @Override public boolean onCapturedPointer (View view, MotionEvent motionEvent) { // Get the coordinates required by your app. float horizontalOffset = motionEvent.getX(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; } });
Unabhängig davon, ob Sie eine benutzerdefinierte Ansicht verwenden oder einen Listener registrieren, erhält die Ansicht eine MotionEvent
mit Zeigerkoordinaten, die relative Bewegungen wie X- oder Y-Deltas angeben, ähnlich den Koordinaten, die von einem Trackball-Gerät geliefert werden. Sie können die Koordinaten mit getX()
und getY()
abrufen.
Aufnahme mit Releasezeiger
Die Ansicht in Ihrer App kann die Zeigererfassung freigeben, indem sie releasePointerCapture()
aufruft, wie im folgenden Codebeispiel gezeigt:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
Das System kann die Erfassung aus der Ansicht wegnehmen, ohne dass Sie releasePointerCapture()
explizit aufrufen. Dies liegt häufig daran, dass die Ansichtshierarchie mit der Ansicht, die die Anfragen erfassen, den Fokus verliert.