Monitora i movimenti del tocco e del puntatore

Prova il metodo Scrivi
Jetpack Compose è il toolkit consigliato per la UI per Android. Scopri come utilizzare il tocco e l'input in Compose.

Questa lezione descrive come tenere traccia dei movimenti negli eventi di contatto.

Un nuovo onTouchEvent() viene attivato Evento ACTION_MOVE ogni volta che cambiano la posizione corrente del contatto, la pressione o le dimensioni. Come descritta in Rileva gesti comuni, questi eventi vengono registrati MotionEvent di onTouchEvent(),

Poiché il tocco basato sulle dita non è sempre la forma più precisa di interazione, 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 che non si muovono (ad esempio un solo tocco), Android include la nozione di dipensione al tocco. Per inclinazione al tocco si intende la distanza in pixel in cui può toccare un utente con un tocco girovagare prima che il gesto venga interpretato come gesto basato sul movimento. Per ulteriori informazioni informazioni su questo argomento, consulta Gestire gli eventi touch in un ViewGroup.

Esistono diversi modi per rilevare il movimento in un gesto, a seconda del le esigenze della tua applicazione. Ecco alcuni esempi:

  • La posizione iniziale e finale di un puntatore, ad esempio lo spostamento di un dal punto A al punto B.
  • La direzione in cui si sposta il puntatore, come stabilito da X e Y coordinate.
  • Cronologia. Puoi conoscere le dimensioni della cronologia di un gesto chiamando il MotionEvent metodo getHistorySize() Puoi quindi ottenere le posizioni, le dimensioni, il tempo e le pressioni di ciascuno eventi storici utilizzando la proprietà getHistorical<Value> di machine learning. La cronologia è utile quando si esegue il rendering di una scia del dito dell'utente, come per il disegno al tocco. Per informazioni dettagliate, consulta il riferimento di MotionEvent.
  • La velocità del puntatore mentre si sposta sul touchscreen.

Consulta le seguenti risorse correlate:

Monitora la velocità

Puoi avere un gesto basato sul movimento basato sulla distanza o sulla direzione il puntatore si sposta. Tuttavia, la velocità è spesso un fattore determinante nel monitoraggio le caratteristiche di un gesto o la decisione dell'esecuzione o meno del gesto. Per rendere il calcolo della velocità, Android fornisce VelocityTracker. VelocityTracker ti aiuta a monitorare la velocità degli eventi touch. È utile per i gesti in cui la velocità è uno dei criteri dei gesti, ad esempio un'avventura.

Ecco un esempio che illustra lo scopo dei metodi in 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, il desktop remoto e i client di virtualizzazione, di non avere più 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 mostrare tutti gli eventi del mouse in una vista mirata nell'app.

Richiedi acquisizione puntatore

Una vista nella tua app può richiedere l'acquisizione del puntatore solo se la gerarchia delle visualizzazioni che contiene lo stato attivo. Per questo motivo, richiedi l'acquisizione del puntatore quando è presente un'azione specifica dell'utente sulla vista, ad esempio durante onClick() o nel onWindowFocusChanged() gestore di eventi della tua attività.

Per richiedere l'acquisizione del puntatore, richiama il metodo requestPointerCapture() nella vista. L'esempio di codice seguente mostra come richiedere il puntatore registrare quando l'utente fa clic su una visualizzazione:

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 nella visualizzazione con stato attivo dell'app, purché si trova nella stessa gerarchia di quella che ha richiesto l'acquisizione. Altro le app smettono di ricevere gli eventi del mouse fino al rilascio dell'acquisizione, inclusi ACTION_OUTSIDE eventi. Android invia eventi di puntatore da origini diverse dal mouse è normale, ma il puntatore del mouse non è più visibile.

Gestire gli eventi del puntatore acquisiti

Una volta che una vista acquisisce correttamente l'acquisizione del puntatore, Android fornisce la del mouse. La vista selezionata può gestire gli eventi eseguendo una delle le seguenti attività:

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;
}

L'esempio di codice che segue 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;
  }
});

Sia che utilizzi una visualizzazione personalizzata sia che registri un listener, la tua visualizzazione riceve un MotionEvent con coordinate del puntatore che specificano i movimenti relativi, ad esempio X o delta Y, simili alle coordinate fornite da un dispositivo trackball. Puoi recupera le coordinate utilizzando getX() e getY().

Acquisizione puntatore di rilascio

La visualizzazione nell'app può rilasciare l'acquisizione del puntatore richiamando releasePointerCapture(), come mostrato nel seguente esempio di codice:

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 fare chiamata releasePointerCapture(), in genere perché la gerarchia di visualizzazione che contiene la vista che consente di acquisire le richieste perde lo stato attivo.