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 chiamatofling()
. Questa tecnica richiede e calcolare gli offset di scorrimentoonDraw()
e chiamapostInvalidate()
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 chiamandoaddUpdateListener()
. Questa tecnica consente di animare le proprietà di unView
.
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();