Un gesto táctil se produce cuando un usuario coloca uno o más dedos en el pantalla táctil, y tu app interpretará este patrón de toques como un gesto. Hay hay dos fases en la detección de gestos:
- Recopilación de datos de eventos táctiles
- Interpretar los datos para determinar si cumplen con los criterios del gestos que admite tu app.
Clases de AndroidX
En los ejemplos de este documento, se usa el
GestureDetectorCompat
y
MotionEventCompat
. Estas clases se encuentran en el repositorio AndroidX
Biblioteca. Usa clases de AndroidX cuando sea posible para brindar compatibilidad con
dispositivos anteriores.
MotionEventCompat
no reemplaza al
MotionEvent
. En cambio, proporciona métodos de utilidades estáticos a los que pasas tu
MotionEvent
para recibir la acción asociada con ese
para cada evento.
Cómo recopilar datos
Cuando un usuario coloca uno o más dedos en la pantalla, se activa
devolución de llamada
onTouchEvent()
en la vista que recibe los eventos táctiles. Para cada secuencia de contacto
eventos, como la posición, la presión, el tamaño y la adición de otro,
dedo, que se identifica como un gesto, onTouchEvent()
es
se activó varias veces.
El gesto comienza cuando el usuario toca la pantalla por primera vez y continúa como
sistema rastrea la posición del dedo o los dedos del usuario y finaliza
capturar el evento final del último dedo del usuario al salir de la pantalla
A lo largo de esta interacción, el MotionEvent
entregó a
onTouchEvent()
proporciona los detalles de cada interacción. Tu app
puede usar los datos proporcionados por el MotionEvent
para determinar si un
importante que realmente importa.
Cómo capturar eventos táctiles para objetos Activity o View
Para interceptar eventos táctiles en un Activity
o
View
, anula la devolución de llamada onTouchEvent()
.
El siguiente fragmento de código usa
getAction()
para extraer la acción que realiza el usuario del parámetro event
.
Esto te proporciona los datos sin procesar que necesitas para determinar si un gesto que te interesa
ocurre.
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); } }
Este código produce mensajes como los siguientes en Logcat a medida que el usuario presiona: toques y mantiene y arrastra:
GESTURES D Action was DOWN GESTURES D Action was UP GESTURES D Action was MOVE
Para gestos personalizados, puedes hacer
tu propio procesamiento en estos eventos
determinar si representan un gesto que necesitas controlar. Sin embargo, si tus
usa gestos comunes, como tocar dos veces, tocar y ejecutar, arrastrar, etcétera,
puedes aprovechar la
GestureDetector
. GestureDetector
facilita la detección de problemas
sin procesar los eventos táctiles individuales. Este es
que se explica con más detalle en Detecta gestos.
Cómo capturar eventos táctiles para una sola vista
Como alternativa a onTouchEvent()
, puedes adjuntar un
View.OnTouchListener
objeto a cualquier View
con el comando
setOnTouchListener()
. Esto permite escuchar eventos táctiles sin subclasificar un
View
existente, como se muestra en el siguiente ejemplo:
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; } });
Ten cuidado de no crear un objeto de escucha que muestre false
para el
ACTION_DOWN
evento.
Si haces esto, el objeto de escucha no se llama para la ejecución
ACTION_MOVE
y
Secuencia ACTION_UP
de
eventos. Esto se debe a que ACTION_DOWN
es el punto de partida para todos
eventos táctiles.
Si estás creando una vista personalizada, puedes anular
onTouchEvent()
, como se describió antes.
Cómo detectar gestos
Android proporciona la clase GestureDetector
para detectar expresiones
y gestos clave. Algunos de los gestos que admite son:
onDown()
,
onLongPress()
,
y
onFling()
Puedes usar GestureDetector
junto con el elemento
onTouchEvent()
descrito anteriormente.
Cómo detectar todos los gestos compatibles
Cuando creas una instancia de un objeto GestureDetectorCompat
, uno de los
de parámetros que toma es una clase que implementa la
GestureDetector.OnGestureListener
interfaz de usuario. GestureDetector.OnGestureListener
notifica a los usuarios cuando un
que ocurra un evento táctil en particular. Para que tus
GestureDetector
para recibir eventos, anular la vista o
método onTouchEvent()
de la actividad y pasar todos los eventos observados
a la instancia del detector.
En el siguiente fragmento, se muestra un valor de true
del elemento
métodos individuales on<TouchEvent>
indica que el
evento táctil. Un valor de retorno de false
pasa eventos.
por la pila de vistas hasta que el toque se controle con éxito.
Si ejecutas el siguiente fragmento en una app de prueba, puedes tener una idea de cómo
acciones se activan cuando interactúas con la pantalla táctil y lo que
el contenido de MotionEvent
es para cada evento táctil. Luego verás
cuántos datos se generan para interacciones simples.
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; } }
Cómo detectar un subconjunto de gestos compatibles
Si solo quieres procesar algunos gestos, puedes extender
GestureDetector.SimpleOnGestureListener
en lugar de implementar GestureDetector.OnGestureListener
interfaz de usuario.
GestureDetector.SimpleOnGestureListener
proporciona un
implementación de todos los
on<TouchEvent>
métodos mostrando
false
para todos. Esto te permite anular solo los métodos que
que te interesa. Por ejemplo, el siguiente fragmento de código crea una clase que extiende
GestureDetector.SimpleOnGestureListener
y anulaciones
onFling()
y onDown()
.
Ya sea que uses GestureDetector.OnGestureListener
o
GestureDetector.SimpleOnGestureListener
, una práctica recomendada es
implementa un método onDown()
que muestre true
. Esta
es que todos los gestos comienzan con un mensaje onDown()
. Si
mostrar false
de onDown()
, como
GestureDetector.SimpleOnGestureListener
lo hace de forma predeterminada, el sistema
supone que deseas ignorar el resto del gesto y los demás métodos de
No se llama a GestureDetector.OnGestureListener
. Esto podría provocar
problemas inesperados en tu aplicación. Solo devolver false
desde
onDown()
si realmente quieres ignorar un gesto completo.
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; } } }
Recursos adicionales
- Descripción general de eventos de entrada
- Descripción general de los sensores
- Cómo crear una vista personalizada interactiva