En esta lección, se describe cómo realizar un seguimiento del movimiento en eventos táctiles.
Un nuevo
onTouchEvent()
se activa con un
ACTION_MOVE
evento
Cada vez que cambia la posición, la presión o el tamaño del contacto táctil actual. Como
como se describe en Cómo detectar gestos comunes, todos
estos eventos se registran en el
Parámetro MotionEvent
de
onTouchEvent()
Debido a que el toque con el dedo no siempre es la forma más precisa de interacción, la detección de eventos táctiles a menudo se basa más en el movimiento que en el simple contacto. Para ayudar a las apps a distinguir entre gestos basados en movimientos (como deslizar el dedo) y gestos sin movimiento (como un toque único), Android incluye la noción de slop táctil. El margen táctil se refiere a la distancia en píxeles que puede deambular antes del gesto se interpreta como un gesto basado en movimiento. Para ver más información sobre este tema, consulta Administrar eventos táctiles de un ViewGroup.
Hay varias formas de rastrear el movimiento de un gesto, según las necesidades de tu aplicación. Estos son algunos ejemplos:
- La posición inicial y final de un puntero, como mover una posición en pantalla objeto del punto A al punto B.
- La dirección en la que viaja el puntero, según lo determinado por las variables Y y X. coordenadas.
- Historial. Puedes buscar el tamaño del historial de un gesto llamando al
Método
MotionEvent
getHistorySize()
Luego, puedes obtener las posiciones, los tamaños, el tiempo y las presiones de cada uno de los de eventos históricos usando la columnagetHistorical<Value>
. El historial es útil cuando se renderiza un rastro del dedo del usuario, como que para el dibujo táctil. Para obtener más información, consulta la referencia deMotionEvent
. - La velocidad del puntero a medida que se mueve por la pantalla táctil.
Consulta los siguientes recursos relacionados:
- Descripción general de eventos de entrada
- Descripción general de los sensores
- Cómo crear una vista personalizada interactiva
Cómo hacer un seguimiento de la velocidad
Puedes tener un gesto basado en movimiento según la distancia o dirección
viaja el puntero. Sin embargo, la velocidad suele ser un factor determinante en el seguimiento
las características de un gesto o decidir si el gesto ocurrió. Para hacer
de procesamiento de velocidad, Android proporciona la
VelocityTracker
.
VelocityTracker
te ayuda a realizar un seguimiento de la velocidad de los eventos táctiles. Esta información es útil
para gestos en los que la velocidad es parte de los criterios del gesto, por ejemplo,
un lanzamiento.
Este es un ejemplo que ilustra el propósito de los métodos en la
API de VelocityTracker
:
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; } }
Cómo usar la captura del puntero
Algunas apps, como las de juegos, escritorio remoto y clientes de virtualización, control sobre el puntero del mouse. La captura del puntero es una función disponible en Android 8.0 (nivel de API 26) y versiones posteriores, que proporciona este control entregar todos los eventos del mouse a una vista enfocada en tu app.
Cómo solicitar la captura del puntero
Una vista en tu app puede solicitar la captura del puntero solo cuando la jerarquía de vistas que
contiene el foco. Por este motivo, solicita la captura del puntero cuando haya un
acción específica del usuario en la vista, por ejemplo, durante una
onClick()
evento o en la
onWindowFocusChanged()
de eventos de tu actividad.
Para solicitar la captura del puntero, llama al
requestPointerCapture()
de la vista. En el siguiente ejemplo de código, se muestra cómo solicitar un puntero
capturar cuando el usuario hace clic en una vista:
Kotlin
fun onClick(view: View) { view.requestPointerCapture() }
Java
@Override public void onClick(View view) { view.requestPointerCapture(); }
Una vez que se realiza correctamente la solicitud para capturar el puntero, Android llama a
onPointerCaptureChange(true)
El sistema envía los eventos del mouse a la vista enfocada en tu app siempre que
está en la misma jerarquía que la que solicitó la captura. Otra opción
las aplicaciones dejan de recibir eventos del mouse hasta que se libera la captura, lo que incluye
ACTION_OUTSIDE
eventos. Android entrega eventos del puntero de fuentes distintas al mouse como
normal, pero el puntero del mouse ya no está visible.
Cómo controlar eventos del puntero capturados
Una vez que una vista adquiere correctamente la captura del puntero, Android entrega el eventos del mouse. Tu vista enfocada puede controlar los eventos realizando una de las las siguientes tareas:
- Si usas una vista personalizada, anula
onCapturedPointerEvent(MotionEvent)
- De lo contrario, registra un
OnCapturedPointerListener
En el siguiente ejemplo de código, se muestra cómo implementar
onCapturedPointerEvent(MotionEvent)
:
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; }
En el siguiente ejemplo de código, se muestra cómo registrar un
OnCapturedPointerListener
:
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; } });
Ya sea que uses una vista personalizada o registres un objeto de escucha, tu vista recibe un
MotionEvent
con coordenadas de puntero que especifican movimientos relativos, como X
o Y deltas, similares a las coordenadas entregadas por un dispositivo de bola de seguimiento. Puedes
recuperar las coordenadas
getX()
y
getY()
Cómo liberar la captura del puntero
La vista de tu app puede liberar la captura del puntero llamando
releasePointerCapture()
:
como se muestra en el siguiente ejemplo de código:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
El sistema puede quitar la captura de la vista sin que indiques explícitamente
llamando a releasePointerCapture()
, por lo general, porque la jerarquía de vistas
con la vista que solicita la captura pierde el foco.