Häufig verwendete Bewegungen erkennen

Schreiben Sie jetzt
Jetpack Compose ist das empfohlene UI-Toolkit für Android. Weitere Informationen zur Verwendung von Berührungen und Eingaben in „Schreiben“

Eine Touch-Geste erfolgt, wenn ein Nutzer einen oder mehrere Finger auf den Touchscreen legt und deine App dieses Berührungsmuster als Geste interpretiert. Die Gestenerkennung gliedert sich in zwei Phasen:

  1. Touch-Ereignisdaten werden erfasst.
  2. Interpretieren der Daten, um festzustellen, ob sie die Kriterien für die von deiner 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 bietet es statische Dienstprogrammmethoden, 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 dem Bildschirm platziert, wird dadurch der Callback onTouchEvent() in der Ansicht ausgelöst, die die Touch-Ereignisse empfängt. Für jede Folge von Berührungsereignissen – z. B. Position, Druck, Größe und Hinzufügen eines anderen Fingers –, die als Geste erkannt wird, 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 mit der Erfassung des letzten Ereignisses, bei dem der letzte Finger des Nutzers den Bildschirm verlässt. Während dieser Interaktion liefert die an onTouchEvent() gelieferte MotionEvent die Details zu jeder Interaktion. Ihre Anwendung kann anhand der von der MotionEvent bereitgestellten Daten feststellen, ob eine für sie relevante Geste erfolgt.

Touch-Ereignisse für eine Aktivität oder Ansicht erfassen

Wenn du Touch-Ereignisse in einem Activity- oder View-Element abfangen möchtest, überschreibe den onTouchEvent()-Callback.

Im folgenden Code-Snippet wird mit getAction() die vom Nutzer ausgeführte Aktion aus dem Parameter event extrahiert. So erhältst du die erforderlichen Rohdaten, um festzustellen, ob eine für dich relevante 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 folgende in Logcat, 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 kannst du diese Ereignisse dann selbst verarbeiten, um festzustellen, ob sie eine Geste darstellen, die du verarbeiten musst. Wenn Ihre App jedoch gängige Gesten wie Doppeltippen, Berühren und Halten, Wischen usw. verwendet, können Sie die GestureDetector-Klasse nutzen. Mit GestureDetector kannst du häufige Touch-Gesten einfacher erkennen, ohne die einzelnen Touch-Ereignisse selbst zu verarbeiten. Weitere Informationen dazu finden Sie unter Gesten erkennen.

Touch-Ereignisse für eine einzige Ansicht erfassen

Als Alternative zu onTouchEvent() können Sie mit der Methode setOnTouchListener() ein View.OnTouchListener-Objekt an jedes View-Objekt anhängen. So ist es möglich, auf Touch-Ereignisse zu warten, ohne eine vorhandene View-Klasse abgeleitet zu haben, 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, einen Listener zu erstellen, der false für das Ereignis ACTION_DOWN zurückgibt. In diesem Fall wird der Listener für die nachfolgende Ereignissequenz ACTION_MOVE und ACTION_UP 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.

Gesten erkennen

Android bietet die Klasse GestureDetector zur Erkennung gängiger Touch-Gesten. Zu den unterstützten Gesten gehören onDown(), onLongPress() und onFling(). Sie können GestureDetector in Verbindung mit der zuvor beschriebenen Methode onTouchEvent() verwenden.

Alle unterstützten Touch-Gesten erkennen

Wenn Sie ein GestureDetectorCompat-Objekt instanziieren, ist einer der erforderlichen Parameter eine Klasse, die die GestureDetector.OnGestureListener-Schnittstelle implementiert. GestureDetector.OnGestureListener benachrichtigt Nutzer, wenn ein bestimmtes Touch-Ereignis auftritt. 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 zeigt ein Rückgabewert von true aus den einzelnen on<TouchEvent>-Methoden an, dass das Touch-Ereignis verarbeitet wird. Beim Rückgabewert false werden die Ereignisse durch den Ansichtsstapel geleitet, bis die Berührung erfolgreich verarbeitet wurde.

Wenn du das folgende Snippet in einer Test-App ausführst, kannst du einen Eindruck davon bekommen, wie Aktionen ausgelöst werden, wenn du mit dem Touchscreen interagierst, und was der Inhalt der MotionEvent für die einzelnen Touch-Ereignisse 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;
    }
}

Bestimmte unterstützte Touch-Gesten erkennen

Wenn Sie nur wenige Gesten verarbeiten möchten, können Sie GestureDetector.SimpleOnGestureListener erweitern, anstatt die GestureDetector.OnGestureListener-Oberfläche zu implementieren.

GestureDetector.SimpleOnGestureListener bietet eine Implementierung für alle on<TouchEvent>-Methoden, indem false für alle zurückgegeben wird. So können Sie nur die für Sie relevanten Methoden überschreiben. 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 du false von onDown() zurückgibst, wie es standardmäßig bei GestureDetector.SimpleOnGestureListener der Fall ist, geht das System davon aus, dass du den Rest der Geste ignorieren möchtest. Die anderen Methoden von GestureDetector.OnGestureListener werden nicht aufgerufen. Das kann zu unerwarteten Problemen in deiner App führen. Gib false nur von onDown() zurück, wenn du eine ganze Geste wirklich ignorieren möchtest.

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