Questa lezione descrive come tenere traccia dei movimenti negli eventi di tocco.
Un nuovo elemento onTouchEvent()
viene attivato con un evento ACTION_MOVE
ogni volta che la posizione attuale del contatto di contatto, la pressione o le dimensioni cambiano. Come
descritto in Rileva gesti comuni, tutti
questi eventi vengono registrati nel
parametro MotionEvent
di
onTouchEvent()
.
Poiché il tocco basato sulle dita non è sempre la forma di interazione più precisa, il rilevamento degli eventi tocco si basa spesso più sul movimento che sul semplice contatto. Per aiutare le app a distinguere tra gesti basati sul movimento (ad esempio uno scorrimento) e non mobili (ad esempio un singolo tocco), Android include la nozione di inclinazione del tocco. La inclinazione al tocco si riferisce alla distanza in pixel che il tocco dell'utente può vagare prima che il gesto venga interpretato come un gesto basato sul movimento. Per ulteriori informazioni su questo argomento, consulta Gestire gli eventi tocco in un ViewGroup.
Esistono diversi modi per tenere traccia dei movimenti in un gesto, a seconda delle esigenze della tua applicazione. Ecco alcuni esempi:
- La posizione iniziale e finale di un puntatore, ad esempio lo spostamento di un oggetto sullo schermo dal punto A al punto B.
- La direzione in cui si muove il puntatore, come determinata dalle coordinate X e Y.
- Cronologia. Puoi trovare la dimensione della cronologia di un gesto chiamando il
metodo
MotionEvent
getHistorySize()
. Puoi quindi ottenere posizioni, dimensioni, tempo e pressioni di ciascuno degli eventi storici usando i metodigetHistorical<Value>
degli eventi di movimento. La cronologia è utile per il rendering di una traccia del dito dell'utente, ad esempio per il tocco. Per informazioni dettagliate, consulta il riferimentoMotionEvent
. - La velocità del puntatore mentre si sposta sul touchscreen.
Fai riferimento alle seguenti risorse correlate:
- Panoramica degli eventi di input
- Panoramica dei sensori
- Rendere interattiva una visualizzazione personalizzata
Velocità del rilevamento
Puoi avere un gesto basato sul movimento basato sulla distanza o sulla direzione
di spostamento del puntatore. Tuttavia, la velocità è spesso un fattore determinante nel tenere traccia delle
caratteristiche di un gesto o nel decidere se si è verificato il gesto. Per semplificare il calcolo della velocità, Android fornisce la classe VelocityTracker
.
VelocityTracker
ti aiuta a monitorare la velocità degli eventi tocco. È utile per i gesti in cui la velocità fa parte dei criteri per il gesto, ad esempio uno sfioramento.
Ecco un esempio che illustra lo scopo dei metodi nell'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; } }
Usa acquisizione con puntatore
Alcune app, come giochi e client di desktop remoto e di virtualizzazione, traggono vantaggio dall'avere il controllo sul puntatore del mouse. L'acquisizione del puntatore è una funzionalità disponibile in Android 8.0 (livello API 26) e versioni successive che offre questo controllo pubblicando tutti gli eventi del mouse in una visualizzazione specifica nella tua app.
Richiedi acquisizione del puntatore
Una vista nella tua app può richiedere l'acquisizione del puntatore solo quando la gerarchia delle visualizzazioni che la contiene è attiva. Per questo motivo, richiedi l'acquisizione del puntatore quando c'è un'azione utente specifica nella vista, ad esempio durante un evento onClick()
o nel gestore eventi onWindowFocusChanged()
della tua attività.
Per richiedere l'acquisizione del puntatore, chiama il metodo
requestPointerCapture()
nella vista. Il seguente esempio di codice mostra come richiedere l'acquisizione
con puntatore quando l'utente fa clic su una vista:
Kotlin
fun onClick(view: View) { view.requestPointerCapture() }
Java
@Override public void onClick(View view) { view.requestPointerCapture(); }
Quando la richiesta per acquisire il puntatore ha esito positivo, Android chiama
onPointerCaptureChange(true)
.
Il sistema invia gli eventi del mouse alla visualizzazione con stato attivo della tua app purché si trovi nella stessa gerarchia di visualizzazione della vista che ha richiesto l'acquisizione. Altre
app non ricevono più eventi del mouse fino al rilascio dell'acquisizione, inclusi gli
eventi ACTION_OUTSIDE
. Android fornisce eventi di puntatore da origini diverse dal mouse, come di consueto, ma il puntatore del mouse non è più visibile.
Gestire gli eventi di puntatore acquisiti
Una volta che una visualizzazione acquisisce correttamente l'acquisizione del puntatore, Android invia gli eventi del mouse. La visualizzazione con stato attivo può gestire gli eventi eseguendo una delle seguenti attività:
- Se utilizzi una visualizzazione personalizzata, esegui l'override di
onCapturedPointerEvent(MotionEvent)
. - In caso contrario, registra un
OnCapturedPointerListener
.
Il seguente esempio di codice mostra come implementare
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; }
Il seguente esempio di codice mostra come registrare 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; } });
A prescindere dal fatto che utilizzi una visualizzazione personalizzata o registri un listener, la visualizzazione riceve un elemento
MotionEvent
con coordinate del puntatore che specificano movimenti relativi, ad esempio delta X
o Y, simili alle coordinate fornite da un dispositivo trackball. Puoi
recuperare le coordinate utilizzando
getX()
e
getY()
.
Rilascia acquisizione del puntatore
La visualizzazione nella tua app può rilasciare l'acquisizione del puntatore chiamando
releasePointerCapture()
,
come mostrato nell'esempio di codice che segue:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
Il sistema può rimuovere l'acquisizione dalla visualizzazione senza che tu debba chiamare
esplicitamente releasePointerCapture()
, in genere perché la gerarchia
delle visualizzazioni contenente la visualizzazione su cui viene eseguita l'acquisizione delle richieste perde lo stato attivo.