Questa lezione descrive come tenere traccia dei movimenti negli eventi di contatto.
Un nuovo
onTouchEvent()
viene attivato con un evento
ACTION_MOVE
ogni volta che la posizione attuale del contatto del 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 di tocco si basa spesso più sul movimento che su un semplice contatto. Per aiutare le app a distinguere tra gesti basati sul movimento (ad esempio lo scorrimento) e gesti non di movimento (ad esempio un singolo tocco), Android include la nozione di inclinazione al tocco. Slop al tocco indica la distanza in pixel che l'utente può muovere con il tocco prima che il gesto venga interpretato come gesto basato sul movimento. Per ulteriori informazioni su questo argomento, vedi Gestire gli eventi touch in un ViewGroup.
Esistono diversi modi per rilevare il movimento in un gesto, a seconda delle esigenze dell'applicazione. Ecco alcuni esempi:
- La posizione iniziale e finale di un puntatore, ad esempio spostare un oggetto sullo schermo da un punto A a un punto B.
- La direzione in cui si sposta il puntatore, come determinato dalle coordinate X e Y.
- Cronologia. Puoi conoscere le dimensioni della cronologia di un gesto chiamando il
metodo
MotionEvent
getHistorySize()
. Puoi quindi ottenere posizioni, dimensioni, tempo e pressione di ciascuno degli eventi storici utilizzando i metodigetHistorical<Value>
dell'evento di movimento. La cronologia è utile quando si esegue il rendering di una scia del dito dell'utente, ad esempio per il disegno tattile. Per informazioni dettagliate, consulta il riferimento diMotionEvent
. - La velocità del puntatore mentre si sposta sul touchscreen.
Consulta le seguenti risorse correlate:
- Panoramica degli eventi di input
- Panoramica dei sensori
- Rendere interattiva una visualizzazione personalizzata
Monitora la velocità
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 monitorare
le caratteristiche di un gesto o nel decidere se il gesto si è verificato. Per semplificare il calcolo della velocità, Android fornisce la classe VelocityTracker
.
VelocityTracker
ti aiuta a monitorare la velocità degli eventi touch. Ciò è utile per i gesti in cui la velocità fa parte dei criteri del gesto, ad esempio l'inversione.
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 puntatore
Alcune app, come i giochi, i client di desktop remoto e di virtualizzazione, traggono vantaggio dal controllo del puntatore del mouse. L'acquisizione del puntatore è una funzionalità disponibile in Android 8.0 (livello API 26) e versioni successive che fornisce questo controllo pubblicando tutti gli eventi del mouse in una vista mirata all'interno dell'app.
Richiedi acquisizione puntatore
Una vista nella tua app può richiedere l'acquisizione del puntatore solo quando la gerarchia delle visualizzazioni che lo contiene è attiva. Per questo motivo, l'acquisizione del puntatore della richiesta quando viene rilevata un'azione specifica dell'utente nella vista, ad esempio durante un evento onClick()
o nel gestore di eventi onWindowFocusChanged()
della tua attività.
Per richiedere l'acquisizione del puntatore, chiama il metodo requestPointerCapture()
nella vista. L'esempio di codice riportato di seguito mostra come richiedere l'acquisizione
del 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 di acquisizione del puntatore ha esito positivo, Android chiama
onPointerCaptureChange(true)
.
Il sistema invia gli eventi del mouse alla vista con lo stato attivo dell'app, purché si trovi nella stessa gerarchia di quella che ha richiesto l'acquisizione. Altre
app non ricevono gli eventi del mouse fino al rilascio dell'acquisizione, inclusi gli eventi
ACTION_OUTSIDE
. Android invia gli eventi del puntatore da origini diverse dal mouse come
normalmente, ma il puntatore del mouse non è più visibile.
Gestire gli eventi del puntatore acquisiti
Dopo che una vista acquisisce correttamente l'acquisizione del puntatore, Android genera gli eventi del mouse. La vista selezionata può gestire gli eventi eseguendo una delle seguenti attività:
- Se utilizzi una visualizzazione personalizzata, sostituisci
onCapturedPointerEvent(MotionEvent)
. - In caso contrario, registra una
OnCapturedPointerListener
.
L'esempio di codice seguente 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; }
L'esempio di codice seguente mostra come registrare una 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; } });
Sia che utilizzi una visualizzazione personalizzata o registri un listener, la vista riceve un
MotionEvent
con coordinate del puntatore che specificano movimenti relativi, come i delta X
o Y, simili alle coordinate fornite da un dispositivo trackball. Puoi
recuperare le coordinate utilizzando
getX()
e
getY()
.
Acquisizione puntatore di rilascio
La visualizzazione nella tua app può rilasciare l'acquisizione del puntatore richiamando
releasePointerCapture()
,
come mostrato nell'esempio di codice seguente:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
Il sistema può rimuovere l'acquisizione dalla vista senza che tu debba chiamare esplicitamente releasePointerCapture()
, in genere perché la gerarchia di visualizzazione contenente la vista che le richieste di acquisizione perde lo stato attivo.