Esta lição descreve como rastrear o movimento em eventos de toque.
Um novo
onTouchEvent()
é acionado com uma
ACTION_MOVE
evento
sempre que a posição, pressão ou tamanho do contato de toque atual mudar. Conforme
descritos em Detectar gestos comuns, todos
esses eventos são registrados
Parâmetro MotionEvent
de
onTouchEvent()
.
Como o toque com o dedo nem sempre é a forma mais precisa de interação, a detecção de eventos de toque geralmente se baseia mais no movimento do que em um simples contato. Para ajudar os apps a distinguir entre gestos de movimento (como deslizar) e gestos sem movimento (como um único toque), o Android inclui a noção de tolerância de toque. A tolerância de toque refere-se à distância em pixels que o toque do usuário pode vagar antes de o gesto ser interpretado como um gesto de movimento. Para mais informações sobre este tópico, consulte Gerenciar eventos de toque em um ViewGroup.
Há várias maneiras de acompanhar o movimento em um gesto, dependendo as necessidades do seu aplicativo. Confira alguns exemplos:
- As posições inicial e final de um ponteiro, como mover um objeto na tela do ponto A ao ponto B.
- A direção em que o ponteiro está viajando, conforme determinado pelos atributos X e Y. coordenadas.
- O histórico. Você pode encontrar o tamanho do histórico de um gesto chamando o
Método
MotionEvent
getHistorySize()
. É possível saber as posições, tamanhos, horários e pressões de cada um eventos históricos usando a funçãogetHistorical<Value>
métodos. O histórico é útil para renderizar um rastro do dedo do usuário, como quanto ao desenho por toque. Consulte a referência doMotionEvent
para mais detalhes. - A velocidade do ponteiro conforme ele se move pela tela touchscreen.
Confira estes recursos relacionados:
- Visão geral dos eventos de entrada
- Visão geral dos sensores
- Tornar uma visualização personalizada interativa
Velocidade de rastreamento
É possível ter um gesto de movimento baseado na distância ou direção
o cursor percorre. No entanto, a velocidade costuma ser um fator determinante no rastreamento
as características de um gesto ou decidir se ele ocorreu. Para fazer
o cálculo da velocidade mais fácil, o Android fornece a
classe VelocityTracker
.
VelocityTracker
ajuda a rastrear a velocidade dos eventos de toque. Isso é útil
para gestos em que a velocidade faz parte dos critérios do gesto, como
rapidamente.
Aqui está um exemplo que ilustra a finalidade dos métodos na
API 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; } }
Usar captura de ponteiro
Alguns aplicativos, como jogos e clientes de área de trabalho remota e virtualização, se beneficiam controle o ponteiro do mouse. A captura do ponteiro é um recurso disponíveis no Android 8.0 (API de nível 26) e versões posteriores que oferecem esse controle entregar todos os eventos do mouse para uma visualização focada no app;
Solicitar captura de ponteiro
Uma visualização no app pode solicitar a captura de ponteiro somente quando a hierarquia de visualizações que
contém o foco. Por isso, solicite a captura do ponteiro quando houver um
ação específica do usuário na visualização, como durante um
onClick()
ou no
onWindowFocusChanged()
manipulador de eventos da sua atividade.
Para solicitar a captura de ponteiro, chame o método
requestPointerCapture()
na visualização. O exemplo de código abaixo mostra como solicitar o ponteiro
capturar quando o usuário clica em uma visualização:
Kotlin
fun onClick(view: View) { view.requestPointerCapture() }
Java
@Override public void onClick(View view) { view.requestPointerCapture(); }
Quando a solicitação para capturar o ponteiro for bem-sucedida, o Android vai chamar
onPointerCaptureChange(true)
O sistema entrega os eventos de mouse para a visualização focada no seu app, desde que
ele está na mesma hierarquia de visualização que solicitou a captura. Outra opção
os aplicativos param de receber eventos de mouse até que a captura seja liberada, incluindo
ACTION_OUTSIDE
eventos. O Android entrega eventos de ponteiro de outras origens além do mouse, como
normal, mas o ponteiro do mouse não estará mais visível.
Processar eventos de ponteiro capturados
Depois que uma visualização adquire a captura do ponteiro, o Android mostra o eventos do mouse. A visualização em foco pode lidar com os eventos realizando um dos as seguintes tarefas:
- Se você está usando uma visualização personalizada, modifique
onCapturedPointerEvent(MotionEvent)
- Caso contrário, registre um
OnCapturedPointerListener
O exemplo de código abaixo mostra como 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; }
O exemplo de código a seguir mostra como registrar
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; } });
Se você usar uma visualização personalizada ou registrar um listener, sua visualização receberá uma
MotionEvent
por coordenadas de ponteiro que especificam movimentos relativos, como X.
ou deltas Y, semelhantes às coordenadas entregues por um dispositivo trackball. Você pode
recuperar as coordenadas usando
getX()
e
getY()
Liberar captura de ponteiro
A visualização no seu app pode liberar a captura do ponteiro chamando
releasePointerCapture()
,
conforme mostrado neste exemplo de código:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
O sistema pode tirar a captura da visualização sem você explicitamente
chamar releasePointerCapture()
, geralmente porque a hierarquia de visualização
que contém a visualização que solicita a captura perde o foco.