Um gesto multitoque ocorre quando vários ponteiros (dedos) tocam na tela ao mesmo tempo. Este documento descreve como detectar gestos que envolvem vários ponteiros.
Rastrear vários ponteiros
Quando vários ponteiros tocam na tela ao mesmo tempo, o sistema gera os seguintes eventos de toque:
ACTION_DOWN
: enviada quando o primeiro ponteiro toca na tela. Isso inicia o gesto. A os dados desse ponteiro estão sempre no índice0
daMotionEvent
.ACTION_POINTER_DOWN
: é enviado quando outros ponteiros entram na tela após o primeiro. Você pode conseguir o índice do ponteiro que acabou de descer usandogetActionIndex()
:ACTION_MOVE
: enviado quando ocorre uma mudança em um gesto, envolvendo qualquer número de ponteiros.ACTION_POINTER_UP
: enviado quando um ponteiro não primário sobe. Você pode obter o índice do que acabou de subir usandogetActionIndex()
.ACTION_UP
: enviado quando o último ponteiro sai da tela.ACTION_CANCEL
: indica que todo o gesto, incluindo todos os ponteiros, foi cancelado.
Iniciar e encerrar gestos
Um gesto é uma série de eventos que começa com uma ACTION_DOWN
.
evento e terminando com ACTION_UP
ou
evento ACTION_CANCEL
. Há um gesto ativo por vez. A
as ações DOWN, MOVE, UP e CANCEL são aplicadas a todo o gesto. Por exemplo, uma
Um evento com ACTION_MOVE
pode indicar um movimento para todos os ponteiros.
para baixo naquele momento.
Acompanhar os ponteiros
Usar o índice e o ID do ponteiro para rastrear os ponteiros individuais
posições em um MotionEvent
.
- Índice: um
MotionEvent
armazena o ponteiro. informações em uma matriz. O índice de um ponteiro é sua posição dentro deste matriz. A maioria dos métodosMotionEvent
usa o índice de ponteiro como um parâmetro, em vez do ID do ponteiro. - ID: cada ponteiro também tem um mapeamento de ID que permanece persistente em eventos de toque para permitir o rastreamento de um ponteiro individual em todo o gesto.
Os ponteiros individuais aparecem dentro de um evento de movimento em uma ordem indefinida. Assim,
o índice de um ponteiro pode mudar de um evento para o próximo, mas o ID do ponteiro
de um ponteiro vai permanecer constante enquanto ele permanecer
ativos. Use o
getPointerId()
para obter o ID de um ponteiro a fim de rastreá-lo em todas as
eventos de movimento em um gesto. Em seguida, para eventos de movimento sucessivos, use o método
findPointerIndex()
para obter o índice do ponteiro de um determinado ID de ponteiro nesse evento de movimento.
Exemplo:
Kotlin
private var mActivePointerId: Int = 0 override fun onTouchEvent(event: MotionEvent): Boolean { ... // Get the pointer ID. mActivePointerId = event.getPointerId(0) // ... Many touch events later... // Use the pointer ID to find the index of the active pointer // and fetch its position. val (x: Float, y: Float) = event.findPointerIndex(mActivePointerId).let { pointerIndex -> // Get the pointer's current position. event.getX(pointerIndex) to event.getY(pointerIndex) } ... }
Java
private int mActivePointerId; public boolean onTouchEvent(MotionEvent event) { ... // Get the pointer ID. mActivePointerId = event.getPointerId(0); // ... Many touch events later... // Use the pointer ID to find the index of the active pointer // and fetch its position. int pointerIndex = event.findPointerIndex(mActivePointerId); // Get the pointer's current position. float x = event.getX(pointerIndex); float y = event.getY(pointerIndex); ... }
Para oferecer suporte a vários ponteiros de toque, é possível armazenar todos os ponteiros ativos em cache com
os IDs deles no ACTION_POINTER_DOWN
e
Horário do evento: ACTION_DOWN
. Remova os ponteiros do cache em
os eventos ACTION_POINTER_UP
e ACTION_UP
. Talvez você
a achar esses IDs armazenados em cache úteis para lidar corretamente com outros eventos de ação. Para
exemplo, ao processar um evento ACTION_MOVE
, encontre o índice para
cada ID de ponteiro ativo armazenado em cache, recupere as coordenadas do ponteiro usando o
getX()
e
getY()
e compare essas coordenadas com as coordenadas em cache para
descobrir quais ponteiros se moveram.
Usar a função getActionIndex()
com
Eventos ACTION_POINTER_UP
e ACTION_POINTER_DOWN
. Não use essa função com eventos ACTION_MOVE
, porque ela
sempre retorna 0
.
Recuperar MotionEvent
ações
Use o
getActionMasked()
ou a versão de compatibilidade
MotionEventCompat.getActionMasked()
para recuperar a ação de um MotionEvent
. Ao contrário do anterior
getAction()
método, o getActionMasked()
foi projetado para funcionar com vários
ponteiros. Ele retorna a ação sem os índices de ponteiro. Para ações com um
índice de ponteiro válido, use getActionIndex()
para retornar o índice de
os ponteiros associados à ação, conforme mostrado no snippet a seguir:
Kotlin
val (xPos: Int, yPos: Int) = MotionEventCompat.getActionMasked(event).let { action -> Log.d(DEBUG_TAG, "The action is ${actionToString(action)}") // Get the index of the pointer associated with the action. MotionEventCompat.getActionIndex(event).let { index -> // The coordinates of the current screen contact, relative to // the responding View or Activity. MotionEventCompat.getX(event, index).toInt() to MotionEventCompat.getY(event, index).toInt() } } if (event.pointerCount > 1) { Log.d(DEBUG_TAG, "Multitouch event") } else { // Single touch event. Log.d(DEBUG_TAG, "Single touch event") } ... // Given an action int, returns a string description. fun actionToString(action: Int): String { return when (action) { MotionEvent.ACTION_DOWN -> "Down" MotionEvent.ACTION_MOVE -> "Move" MotionEvent.ACTION_POINTER_DOWN -> "Pointer Down" MotionEvent.ACTION_UP -> "Up" MotionEvent.ACTION_POINTER_UP -> "Pointer Up" MotionEvent.ACTION_OUTSIDE -> "Outside" MotionEvent.ACTION_CANCEL -> "Cancel" else -> "" } }
Java
int action = MotionEventCompat.getActionMasked(event); // Get the index of the pointer associated with the action. int index = MotionEventCompat.getActionIndex(event); int xPos = -1; int yPos = -1; Log.d(DEBUG_TAG,"The action is " + actionToString(action)); if (event.getPointerCount() > 1) { Log.d(DEBUG_TAG,"Multitouch event"); // The coordinates of the current screen contact, relative to // the responding View or Activity. xPos = (int)MotionEventCompat.getX(event, index); yPos = (int)MotionEventCompat.getY(event, index); } else { // Single touch event. Log.d(DEBUG_TAG,"Single touch event"); xPos = (int)MotionEventCompat.getX(event, index); yPos = (int)MotionEventCompat.getY(event, index); } ... // Given an action int, returns a string description public static String actionToString(int action) { switch (action) { case MotionEvent.ACTION_DOWN: return "Down"; case MotionEvent.ACTION_MOVE: return "Move"; case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down"; case MotionEvent.ACTION_UP: return "Up"; case MotionEvent.ACTION_POINTER_UP: return "Pointer Up"; case MotionEvent.ACTION_OUTSIDE: return "Outside"; case MotionEvent.ACTION_CANCEL: return "Cancel"; } return ""; }
Outros recursos
Para mais informações relacionadas aos eventos de entrada, consulte os referências:
- Visão geral dos eventos de entrada
- Sensores visão geral
- Personalize conferir o conteúdo interativo
- Arrastar e dimensionar