Rendere interattiva una visualizzazione personalizzata

Prova il metodo Scrivi
Jetpack Compose è il toolkit consigliato per la UI per Android. Scopri come utilizzare i layout in Compose.

La creazione di un'interfaccia utente è solo una parte della creazione di una vista personalizzata. Devi inoltre fare in modo che la propria visualizzazione risponda all'input dell'utente in un modo simile l'azione reale che stai imitando.

Fai in modo che gli oggetti nella tua app agiscano come quelli reali. Ad esempio, non permettere nella tua app non esistono più e riappaiono altrove, perché gli oggetti nel mondo reale non lo fanno. Puoi invece spostare le immagini da una posizione un'altra.

Gli utenti percepiscono un comportamento o una sensazione anche impercettibile in un'interfaccia e reagiscono meglio sottigliezze che imitano il mondo reale. Ad esempio, quando gli utenti fanno scorrere un oggetto UI, dare loro un senso di inerzia all'inizio che ritarda il movimento. Alla fine del movimento, darà loro un senso di slancio che porti l'oggetto oltre il un'avventura.

Questa pagina mostra come utilizzare le funzionalità del framework Android per aggiungere questi comportamenti del mondo reale alla tua visualizzazione personalizzata.

Puoi trovare ulteriori informazioni correlate in Panoramica degli eventi di input e Animazione proprietà Panoramica.

Gestire i gesti di immissione

Come molti altri framework dell'interfaccia utente, Android supporta un modello di eventi di input. Utente le azioni si trasformano in eventi che attivano callback ed è possibile eseguire l'override i callback per personalizzare il modo in cui l'app risponde all'utente. L'input più comune nel sistema Android è il touch, che attiva onTouchEvent(android.view.MotionEvent). Esegui l'override di questo metodo per gestire l'evento nel seguente modo:

Kotlin

override fun onTouchEvent(event: MotionEvent): Boolean {
    return super.onTouchEvent(event)
}

Java

@Override
   public boolean onTouchEvent(MotionEvent event) {
    return super.onTouchEvent(event);
   }

Gli eventi touch non sono particolarmente utili di per sé. UI touch moderne definire interazioni in termini di gesti quali tocco, tiro, spinta, per scorrere e aumentare lo zoom. Per convertire eventi touch non elaborati in gesti, Android fornisce GestureDetector.

Costruire un GestureDetector passando in un'istanza di una classe che implementa GestureDetector.OnGestureListener. Se vuoi elaborare solo pochi gesti, puoi estendere GestureDetector.SimpleOnGestureListener anziché implementare GestureDetector.OnGestureListener a riga di comando. Ad esempio, questo codice crea una classe che estende GestureDetector.SimpleOnGestureListener e override onDown(MotionEvent).

Kotlin

private val myListener =  object : GestureDetector.SimpleOnGestureListener() {
    override fun onDown(e: MotionEvent): Boolean {
        return true
    }
}

private val detector: GestureDetector = GestureDetector(context, myListener)

Java

class MyListener extends GestureDetector.SimpleOnGestureListener {
   @Override
   public boolean onDown(MotionEvent e) {
       return true;
   }
}
detector = new GestureDetector(getContext(), new MyListener());

Che tu utilizzi o meno GestureDetector.SimpleOnGestureListener, implementare sempre onDown() che restituisce true. Questa operazione è necessaria perché tutti i gesti iniziano con un messaggio onDown(). Se restituisci false da onDown(), come GestureDetector.SimpleOnGestureListener, il sistema presuppone vuoi ignorare il resto del gesto e gli altri metodi GestureDetector.OnGestureListener non vengono chiamati. Solo reso false da onDown() se vuoi ignorare l'intera operazione gesto.

Dopo aver implementato GestureDetector.OnGestureListener e creato un'istanza di GestureDetector, puoi utilizzare GestureDetector per interpretare gli eventi touch che ricevi onTouchEvent().

Kotlin

override fun onTouchEvent(event: MotionEvent): Boolean {
    return detector.onTouchEvent(event).let { result ->
        if (!result) {
            if (event.action == MotionEvent.ACTION_UP) {
                stopScrolling()
                true
            } else false
        } else true
    }
}

Java

@Override
public boolean onTouchEvent(MotionEvent event) {
   boolean result = detector.onTouchEvent(event);
   if (!result) {
       if (event.getAction() == MotionEvent.ACTION_UP) {
           stopScrolling();
           result = true;
       }
   }
   return result;
}

Quando superi onTouchEvent() un evento tocco che non passa riconosce come parte di un gesto, e restituisce false. Puoi quindi eseguire il tuo codice personalizzato di rilevamento dei gesti.

Crea un movimento fisicamente plausibile

I gesti sono un modo efficace per controllare i dispositivi touchscreen, ma possono essere controintuitive e difficili da ricordare a meno che non producano risultati plausibili.

Ad esempio, supponi di voler implementare un gesto di scorrimento orizzontale l'elemento disegnato nella visualizzazione ruota intorno al proprio asse verticale. Questo gesto ha senso se l'UI risponde spostandosi rapidamente nella direzione dell'evoluzione, e poi rallentare, come se l'utente spingesse un volano e lo fa girare.

La documentazione su come anima una scorrimento gesto fornisce una spiegazione dettagliata su come implementare il tuo scoll comportamento degli utenti. Ma simulare la sensazione di un volano non è banale. Molta fisica e la matematica è necessaria per far funzionare correttamente un modello volano. Per fortuna Android offre classi di supporto per simulare questo e altri comportamenti. La Scroller è la base per gestire i gesti di scorrimento come quelli del volano.

Per iniziare un'avventura, chiama fling() con la velocità iniziale e le minime e le massime x e y i valori dell'evoluzione. Per il valore della velocità, puoi utilizzare il valore calcolato GestureDetector.

Kotlin

fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
    scroller.fling(
            currentX,
            currentY,
            (velocityX / SCALE).toInt(),
            (velocityY / SCALE).toInt(),
            minX,
            minY,
            maxX,
            maxY
    )
    postInvalidate()
    return true
}

Java

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   scroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY);
   postInvalidate();
    return true;
}

La chiamata a fling() configura il modello di fisica per l'avventura gesto. Dopodiché, aggiorna Scroller chiamando Scroller.computeScrollOffset() a intervalli regolari. computeScrollOffset() aggiorna la stato interno dell'oggetto Scroller leggendo l'ora attuale e utilizzando il modello fisico per calcolare le posizioni x e y in quel momento nel tempo. Chiama getCurrX() e getCurrY() per recuperare questi valori.

La maggior parte delle visualizzazioni supera x e y dell'oggetto Scroller posizioni direttamente scrollTo(). Questo esempio è un po' diverso: utilizza la posizione di scorrimento x corrente per impostare l'angolo di rotazione della vista.

Kotlin

scroller.apply {
    if (!isFinished) {
        computeScrollOffset()
        setItemRotation(currX)
    }
}

Java

if (!scroller.isFinished()) {
    scroller.computeScrollOffset();
    setItemRotation(scroller.getCurrX());
}

La classe Scroller calcola le posizioni di scorrimento per te, ma non applica automaticamente queste posizioni alla tua visualizzazione. Applicare nuove coordinate abbastanza spesso per rendere fluida l'animazione di scorrimento. Esistono due modi per fai questo:

  • Forza il nuovo disegno chiamando postInvalidate() dopo aver chiamato fling(). Questa tecnica richiede e calcolare gli offset di scorrimento onDraw() e chiama postInvalidate() ogni volta che l'offset di scorrimento modifiche.
  • Imposta un ValueAnimator da animare per la durata dell'fling e aggiungere un listener da elaborare gli aggiornamenti delle animazioni chiamando addUpdateListener(). Questa tecnica consente di animare le proprietà di un View.

Rendi fluide le tue transizioni

Gli utenti si aspettano che una UI moderna possa passare facilmente da uno stato all'altro: gli elementi UI dissolvenza in entrata e uscita invece di apparire e scomparire, e i movimenti iniziano e terminare in modo fluido anziché iniziare e interrompersi bruscamente. Android animazione della proprietà semplifica le transizioni.

Per utilizzare il sistema di animazione, ogni volta che una proprietà cambia ciò che influisce sulle tue l'aspetto di una visualizzazione, non modificare direttamente la proprietà. Utilizza invece ValueAnimator per apportare la modifica. Nell'esempio seguente, La modifica del componente secondario selezionato nella vista rende l'intero rendering vista ruotare in modo che il puntatore di selezione sia centrato. ValueAnimator cambia la rotazione in un periodo di diverse centinaia millisecondi, invece di impostare immediatamente il nuovo valore di rotazione.

Kotlin

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0).apply {
    setIntValues(targetAngle)
    duration = AUTOCENTER_ANIM_DURATION
    start()
}

Java

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0);
autoCenterAnimator.setIntValues(targetAngle);
autoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION);
autoCenterAnimator.start();

Se il valore che vuoi modificare è uno dei valori di base View eseguire l'animazione è ancora più facile, perché le viste hanno una ViewPropertyAnimator ottimizzato per l'animazione simultanea di più proprietà, come nell'immagine nell'esempio seguente:

Kotlin

animate()
    .rotation(targetAngle)
    .duration = ANIM_DURATION
    .start()

Java

animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();