Rileva gesti comuni

Prova il metodo Scrivi
Jetpack Compose è il toolkit consigliato per la UI per Android. Scopri come utilizzare il tocco e l'input in Compose.

Un gesto di tocco si verifica quando un utente posiziona una o più dita sul il touchscreen e la tua app interpreta questa sequenza di tocchi come un gesto. Là il rilevamento dei gesti prevede due fasi:

  1. Raccolta di dati sugli eventi touch.
  2. Interpretare i dati per determinare se soddisfano i criteri gesti supportati dalla tua app.

Classi AndroidX

Gli esempi in questo documento utilizzano GestureDetectorCompat e MotionEventCompat . Questi corsi sono in AndroidX Raccolta. Se possibile, utilizza le classi AndroidX per garantire la compatibilità con con dispositivi precedenti. MotionEventCompat non sostituisce il MotionEvent . Offre invece metodi di utilità statici a cui passare i tuoi MotionEvent oggetto per ricevere l'azione associata .

Raccogli i dati

Quando un utente posiziona una o più dita sullo schermo, viene attivata la callback onTouchEvent() sulla visualizzazione che riceve gli eventi touch. Per ogni sequenza di tocco come posizione, pressione, dimensione e aggiunta di altri dito—indicato come gesto, onTouchEvent() rappresenta e si sono attivati più volte.

Il gesto inizia quando l'utente tocca per la prima volta lo schermo, poi continua mentre il sistema tiene traccia della posizione del dito o delle dita dell'utente e termina acquisire l'evento finale dell'ultimo dito dell'utente che lascia lo schermo. Nel corso di questa interazione, il MotionEvent è stato inviato a onTouchEvent() fornisce i dettagli di ogni interazione. La tua app possono utilizzare i dati forniti da MotionEvent per determinare se un un gesto a cui tiene.

Acquisire eventi tocco per un'attività o una vista

Per intercettare gli eventi touch in un Activity o View, esegui l'override del callback onTouchEvent().

Il seguente snippet di codice utilizza getAction() per estrarre l'azione eseguita dall'utente dal parametro event. In questo modo ottieni i dati non elaborati necessari per determinare se un gesto ti interessa di Google Cloud.

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);
    }
}

Questo codice produce messaggi come il seguente in Logcat quando l'utente tocca, tocchi e per tenere premuto e trascinare:

GESTURES D   Action was DOWN
GESTURES D   Action was UP
GESTURES D   Action was MOVE

Per i gesti personalizzati, puoi quindi elaborare questi eventi in autonomia per per stabilire se rappresentano un gesto che devi gestire. Tuttavia, se usa gesti comuni, come doppio tocco, tocco e attesa, avvolgente e così via, puoi sfruttare GestureDetector . GestureDetector ti consente di rilevare più facilmente senza elaborare personalmente i singoli eventi tocco. Questo è illustrato in maggiore dettaglio nella sezione Rilevare gesti.

Acquisizione di eventi touch per un'unica visualizzazione

In alternativa a onTouchEvent(), puoi collegare una View.OnTouchListener opporsi a qualsiasi View utilizzando setOnTouchListener() . In questo modo è possibile rimanere in ascolto di eventi touch senza creare sottoclassi View esistente, come mostrato nell'esempio seguente:

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;
    }
});

Presta attenzione alla creazione di un listener che restituisca false per il Evento ACTION_DOWN. In questo caso, il listener non viene chiamato per la query ACTION_MOVE e ACTION_UP sequenza di eventi. Questo perché ACTION_DOWN è il punto di partenza per tutti eventi touch.

Se stai creando una vista personalizzata, puoi sostituirla onTouchEvent(), come descritto in precedenza.

Rileva gesti

Android fornisce la classe GestureDetector per il rilevamento di gesti. Tra i gesti supportati sono inclusi onDown(), onLongPress(), e onFling(). Puoi utilizzare GestureDetector in combinazione con onTouchEvent() descritto in precedenza.

Rileva tutti i gesti supportati

Quando crei un'istanza per un oggetto GestureDetectorCompat, uno dei o i parametri necessari è una classe che implementa GestureDetector.OnGestureListener a riga di comando. GestureDetector.OnGestureListener invia una notifica agli utenti quando si verifica un particolare evento tocco. Per fare in modo che i tuoi GestureDetector oggetto per ricevere eventi, eseguire l'override della vista o il metodo onTouchEvent() dell'attività e trasmette tutti gli eventi osservati all'istanza del rilevatore.

Nel seguente snippet, un valore restituito true dalla i singoli metodi on<TouchEvent> indicano che per gestire l'evento tocco. Un valore restituito pari a false trasmette gli eventi verso il basso fino a quando il tocco non viene gestito correttamente.

Se esegui lo snippet riportato di seguito in un'app di prova, puoi avere un'idea di come azioni vengono attivate quando interagisci con il touchscreen e i contenuti di MotionEvent si riferiscono a ogni evento touch. Quindi vedrai la quantità di dati generati per interazioni semplici.

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;
    }
}

Rileva un sottoinsieme di gesti supportati

Se vuoi elaborare solo pochi gesti, puoi estendere GestureDetector.SimpleOnGestureListener anziché implementare GestureDetector.OnGestureListener a riga di comando.

GestureDetector.SimpleOnGestureListener offre un per tutti on<TouchEvent> metodi tramite la restituzione false per tutti. In questo modo puoi eseguire l'override solo dei metodi a cui tieni. Ad esempio, il seguente snippet di codice crea una classe che si estende GestureDetector.SimpleOnGestureListener e override onFling() e onDown().

Sia che utilizzi GestureDetector.OnGestureListener o GestureDetector.SimpleOnGestureListener, è una best practice implementare un metodo onDown() che restituisca true. Questo perché tutti i gesti iniziano con un messaggio onDown(). Se restituisce false da onDown(), come GestureDetector.SimpleOnGestureListener lo utilizza per impostazione predefinita, presuppone di voler ignorare il resto del gesto e gli altri metodi di GestureDetector.OnGestureListener non vengono chiamati. Ciò potrebbe causare problemi imprevisti nella tua app. Restituisci solo false a partire da onDown() se vuoi davvero ignorare un intero gesto.

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;
        }
    }
}

Risorse aggiuntive