In dieser Lektion wird beschrieben, wie Sie Bewegungen in Touch-Ereignissen erfassen.
Ein neues
onTouchEvent() wird mit einem
ACTION_MOVE-Ereignis ausgelöst, wenn sich die aktuelle Position, der Druck oder die Größe des Touch-Kontakts ändert. Wie unter Häufig verwendete Bewegungen erkennen beschrieben, werden alle diese Ereignisse im Parameter MotionEvent von onTouchEvent() aufgezeichnet.
Da die Interaktion mit den Fingern nicht immer die präziseste Form der Interaktion ist, basiert die Erkennung von Touch-Ereignissen oft eher auf Bewegung als auf einfachem Kontakt. Damit Apps zwischen bewegungsbasierten Gesten (z. B. Wischen) und nicht bewegungsbasierten Gesten (z. B. einmaliges Tippen) unterscheiden können, gibt es in Android das Konzept der Touch-Toleranz. Der Touch-Spielraum bezieht sich auf die Distanz in Pixeln, die ein Nutzer mit seiner Berührung zurücklegen kann, bevor die Geste als bewegungsbasierte Geste interpretiert wird. Weitere Informationen zu diesem Thema finden Sie unter Berührungsereignisse in einer ViewGroup verwalten.
Je nach den Anforderungen Ihrer Anwendung gibt es mehrere Möglichkeiten, Bewegungen in einer Geste zu erfassen. Beispiele:
- Die Start- und Endposition eines Zeigers, z. B. wenn ein Objekt auf dem Bildschirm von Punkt A nach Punkt B verschoben wird.
- Die Richtung, in die sich der Zeiger bewegt, bestimmt durch die X- und Y-Koordinaten.
- Verlauf. Sie können die Größe des Verlaufs einer Geste abrufen, indem Sie die Methode
MotionEventgetHistorySize()aufrufen. Anschließend können Sie mit dengetHistorical<Value>-Methoden des Bewegungsereignisses die Positionen, Größen, Zeit und Drücke der einzelnen historischen Ereignisse abrufen. Der Verlauf ist nützlich, wenn Sie eine Spur des Fingers des Nutzers rendern möchten, z. B. für das Zeichnen per Touch. Weitere Informationen finden Sie in derMotionEvent-Referenz. - Die Geschwindigkeit des Zeigers, wenn er über den Touchscreen bewegt wird.
Weitere Informationen finden Sie in den folgenden Ressourcen:
- Übersicht über Eingabeereignisse
- Sensoren – Übersicht
- Benutzerdefinierte Ansicht interaktiv gestalten
Geschwindigkeit
Sie können eine bewegungsbasierte Geste verwenden, die auf der Entfernung oder Richtung basiert, die der Mauszeiger zurücklegt. Die Geschwindigkeit ist jedoch oft ein entscheidender Faktor, um die Eigenschaften einer Geste zu erfassen oder zu entscheiden, ob die Geste ausgeführt wurde. Um die Berechnung der Geschwindigkeit zu vereinfachen, stellt Android die Klasse VelocityTracker bereit.
Mit VelocityTracker können Sie die Geschwindigkeit von Berührungsereignissen erfassen. Dies ist nützlich für Gesten, bei denen die Geschwindigkeit Teil der Kriterien für die Geste ist, z. B. bei einem schnellen Wischen.
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; } }
Zeigererfassung verwenden
Einige Apps, z. B. Spiele sowie Remote-Desktop- und Virtualisierungsclients, profitieren davon, wenn sie die Kontrolle über den Mauszeiger erhalten. Die Mauszeigererfassung ist eine Funktion, die ab Android 8.0 (API-Level 26) verfügbar ist und diese Steuerung ermöglicht, indem alle Mausereignisse an eine fokussierte Ansicht in Ihrer App gesendet werden.
Zeigererfassung anfordern
Eine Ansicht in Ihrer App kann die Zeigererfassung nur anfordern, wenn die zugehörige Ansichtshierarchie den Fokus hat. Fordern Sie daher die Zeigererfassung an, wenn eine bestimmte Nutzeraktion in der Ansicht erfolgt, z. B. während eines onClick()-Ereignisses oder im onWindowFocusChanged()-Event-Handler Ihrer Aktivität.
Rufen Sie die Methode requestPointerCapture() für die Ansicht auf, um die Zeigererfassung anzufordern. Das folgende Codebeispiel zeigt, wie Sie die Erfassung von Zeigerereignissen 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 Mauszeigers erfolgreich ist, ruft Android onPointerCaptureChange(true) auf.
Das System leitet die Mausereignisse an die fokussierte Ansicht in Ihrer App weiter, solange sie sich in derselben Ansichtshierarchie wie die Ansicht befindet, die die Erfassung angefordert hat. Andere Apps empfangen keine Mausereignisse mehr, bis die Erfassung beendet wird, einschließlich ACTION_OUTSIDE-Ereignissen. Unter Android werden Zeigerereignisse von anderen Quellen als der Maus wie gewohnt übermittelt, der Mauszeiger ist jedoch nicht mehr sichtbar.
Erfasste Zeigerereignisse verarbeiten
Sobald eine Ansicht den Zeiger erfolgreich erfasst hat, werden die Mausereignisse von Android übergeben. Ihre fokussierte Ansicht kann die Ereignisse verarbeiten, indem sie eine der folgenden Aufgaben ausführt:
- Wenn Sie eine benutzerdefinierte Ansicht verwenden, überschreiben Sie
onCapturedPointerEvent(MotionEvent). - Andernfalls registrieren Sie ein
OnCapturedPointerListener.
Das folgende Codebeispiel zeigt, wie Sie onCapturedPointerEvent(MotionEvent) implementieren:
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 Sie ein OnCapturedPointerListener registrieren:
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, empfängt Ihre Ansicht ein 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.
Zeigererfassung beenden
Die Ansicht in Ihrer App kann die Zeigererfassung durch Aufrufen von releasePointerCapture() freigeben, 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 Aufnahme aus der Ansicht entfernen, ohne dass Sie releasePointerCapture() explizit aufrufen. Das ist in der Regel der Fall, wenn die Ansichtshierarchie, die die Ansicht enthält, die die Aufnahme anfordert, den Fokus verliert.