Il sistema di animazione delle proprietà è un solido framework che consente di per animare quasi tutto. Puoi definire un'animazione per modificare qualsiasi proprietà dell'oggetto nel tempo, che attiri o meno lo schermo. L'animazione di una proprietà cambia (un campo di un oggetto) per un determinato periodo di tempo. Per animare un elemento, specifica della proprietà dell'oggetto che vuoi animare, come la posizione di un oggetto sullo schermo, il tempo per cui vuoi eseguire l'animazione e i valori tra i quali eseguire l'animazione.
Il sistema di animazione delle proprietà ti consente di definire le seguenti caratteristiche di una animazione:
- Durata: puoi specificare la durata di un'animazione. La lunghezza predefinita è 300 ms.
- Interpolazione temporale: puoi specificare come vengono calcolati i valori della proprietà come funzione del tempo trascorso attuale dell'animazione.
- Conteggio e comportamento delle ripetizioni: puoi specificare se fare in modo che un'animazione si ripeta o meno quando raggiunge la fine di una durata e quante volte ripetere l'animazione. Puoi anche specifica se desideri che l'animazione venga riprodotta al contrario. Impostazione delle riproduzioni invertite l'animazione in avanti e poi indietro ripetutamente fino a raggiungere il numero di ripetizioni.
- Set di animazioni: puoi raggruppare le animazioni in set logici che vengono riprodotti insieme o in sequenza o dopo determinati ritardi.
- Ritardo aggiornamento frame: puoi specificare la frequenza di aggiornamento dei frame dell'animazione. La l'impostazione predefinita è l'aggiornamento ogni 10 ms, ma la velocità con cui l'applicazione può aggiornare i frame è dipende in ultima analisi da quanto è occupato il sistema nel complesso e da quanto è veloce a gestire il timer sottostante.
Per un esempio completo di animazione della proprietà, consulta la sezione
Classe ChangeColor
in CustomTransizione
di esempio su GitHub.
Come funziona l'animazione della proprietà
Innanzitutto, vediamo come funziona un'animazione con un semplice esempio. La Figura 1 illustra un
oggetto ipotetico animato con la sua proprietà x
, che rappresenta la sua
posizione orizzontale su uno schermo. La durata dell'animazione è impostata su 40 ms e la distanza
per viaggiare è di 40 pixel. Ogni 10 ms, che è la frequenza di aggiornamento predefinita del frame, l'oggetto si sposta
in orizzontale di 10 pixel. Dopo 40 ms, l'animazione si interrompe e l'oggetto termina in
posizione orizzontale 40. Questo è un esempio di animazione con interpolazione lineare, ossia
che si muove a velocità costante.
Puoi anche specificare le animazioni in modo che abbiano un'interpolazione non lineare. La figura 2 illustra una oggetto ipotetico che accelera all'inizio dell'animazione e decelera al fine dell'animazione. L'oggetto si sposta comunque di 40 pixel in 40 ms, ma in modo non lineare. Nella all'inizio, l'animazione accelera fino a metà strada, poi rallenterà dalla a metà strada fino alla fine dell'animazione. Come mostra la Figura 2, la distanza percorsa all'inizio e alla fine dell'animazione è inferiore che al centro.
Vediamo nel dettaglio in che modo i componenti importanti del sistema di animazione delle proprietà calcolerai le animazioni come quelle illustrate sopra. La figura 3 illustra come le classi principali che interagiscono tra loro.
L'oggetto ValueAnimator
tiene traccia dei tempi dell'animazione,
come il tempo di esecuzione dell'animazione e il valore corrente della proprietà
che anima.
ValueAnimator
contiene un elemento TimeInterpolator
, che definisce l'interpolazione dell'animazione, e un elemento TypeEvaluator
, che definisce le modalità di calcolo dei valori per la proprietà
con animazione. Ad esempio, nella Figura 2, il valore TimeInterpolator
utilizzato sarebbe
AccelerateDecelerateInterpolator
e TypeEvaluator
è IntEvaluator
.
Per avviare un'animazione, crea un ValueAnimator
e assegnagli il
i valori iniziali e finali per la proprietà che vuoi animare, insieme alla durata
l'animazione. Quando chiami start()
l'animazione
l'avvio delle operazioni. Durante l'intera animazione, ValueAnimator
calcola una frazione trascorsa
tra 0 e 1, in base alla durata dell'animazione e al tempo trascorso. La
La frazione trascorsa rappresenta la percentuale di tempo di completamento dell'animazione; 0 indica 0%
e 1 indica il 100%. Ad esempio, nella Figura 1, la frazione trascorso a t = 10 ms sarebbe 0,25
perché la durata totale è t = 40 ms.
Quando ValueAnimator
ha terminato di calcolare una frazione passata,
chiama il valore TimeInterpolator
attualmente impostato, per calcolare un
frazione interpolata. Una frazione interpolata mappa la frazione trascorsa a una nuova
frazione che tiene conto dell'interpolazione temporale impostata. Ad esempio, nella Figura 2,
perché l'animazione accelera lentamente, e la frazione interpolata, circa 0,15, è inferiore alla
frazione passata, 0,25, con t = 10 ms. Nella Figura 1, la frazione interpolata è sempre uguale a
la frazione trascorsa.
Quando viene calcolata la frazione interpolata, ValueAnimator
chiama
il valore TypeEvaluator
appropriato per calcolare il valore
che stai animando, in base alla frazione interpolata, al valore iniziale e
valore finale dell'animazione. Ad esempio, nella Figura 2, la frazione interpolata era pari a 0,15 e t =
10 ms, quindi il valore della proprietà in quel momento sarebbe 0,15 × (40 - 0) o 6.
Differenza tra l'animazione della proprietà e l'animazione della vista
Il sistema di animazione della visualizzazione consente di animare solo View
Pertanto, per animare oggetti non View
, devi implementare
con il tuo codice. Il sistema di animazione della visualizzazione è inoltre vincolato in quanto
espone alcuni aspetti di un oggetto View
da animare, come la scalabilità e
la rotazione di una Vista ma non il colore di sfondo, ad esempio.
Un altro svantaggio del sistema di animazione di visualizzazione è che ha modificato solo il punto in cui È stata disegnata la vista, non la vista effettiva. Ad esempio, se hai animato un pulsante per spostarlo sullo schermo, il pulsante disegna correttamente, ma la posizione effettiva in cui è possibile fare clic non cambia, quindi devi implementare una logica per gestire questa situazione.
Con il sistema di animazione delle proprietà, questi vincoli vengono completamente rimossi e puoi proprietà di qualsiasi oggetto (View e non-View) e l'oggetto stesso viene effettivamente modificato. Il sistema di animazione della proprietà è inoltre più efficace nella realizzazione dell'animazione. Alle ore A livello generale, assegni animatori alle proprietà che vuoi animare, come colore, posizione o dimensione e può definire aspetti dell'animazione come l'interpolazione la sincronizzazione di più animatori.
Il sistema di animazione della visualizzazione, tuttavia, richiede meno tempo per la configurazione e meno codice da scrivere. Se l'animazione ti permette di fare tutto ciò che devi fare o se il codice esistente è già funziona nel modo che preferisci, senza bisogno di usare il sistema di animazione della proprietà. Potrebbe anche ha senso utilizzare entrambi i sistemi di animazione per diverse situazioni in base al caso d'uso.
Panoramica dell'API
Puoi trovare la maggior parte delle API del sistema di animazione delle proprietà in android.animation
. Poiché il sistema di visualizzazione delle animazioni
definisce molti interpolatori in android.view.animation
, puoi utilizzare
per questi interpolatori
anche nel sistema di animazione delle proprietà. Le seguenti tabelle descrivono i principali
del sistema di animazione della proprietà.
Il corso Animator
fornisce la struttura di base per la creazione
le animazioni. Normalmente non utilizzi direttamente questo corso perché fornisce solo
che deve essere estesa per supportare completamente i valori di animazione. Le seguenti
le sottoclassi estendono Animator
:
Classe | Descrizione |
---|---|
ValueAnimator |
Il motore di tempo principale per l'animazione delle proprietà, che calcola anche i valori per il parametro
da animare. Include tutte le funzionalità di base per calcolare l'animazione.
e contiene i dettagli di temporizzazione di ciascuna animazione, informazioni sull'eventuale
l'animazione si ripete, i listener che ricevono eventi di aggiornamento e la possibilità di impostare
tipi da valutare. L'animazione delle proprietà è composta da due parti: il calcolo dell'animazione
e l'impostazione di questi valori sull'oggetto e sulla proprietà che vengono animati. ValueAnimator non esegue il secondo pezzo, quindi devi ascoltare
per gli aggiornamenti ai valori calcolati da ValueAnimator e
modificare gli oggetti da animare con la tua logica. Consulta la sezione su
Per ulteriori informazioni, consulta la sezione Animazione con ValueAnimator. |
ObjectAnimator |
Una sottoclasse di ValueAnimator che consente di impostare un target
oggetto e proprietà dell'oggetto da animare. Questa classe aggiorna la proprietà di conseguenza quando
viene calcolato un nuovo valore per l'animazione. Vuoi utilizzare
ObjectAnimator la maggior parte delle volte,
perché semplifica il processo di animazione dei valori sugli oggetti target. Tuttavia,
a volte potresti voler utilizzare direttamente ValueAnimator perché ObjectAnimator ha alcune limitazioni aggiuntive, ad esempio la richiesta di
della funzione di accesso di Google Cloud
nell'oggetto di destinazione. |
AnimatorSet |
Fornisce un meccanismo per raggruppare le animazioni in modo che vengano eseguite relazione tra loro. Puoi impostare le animazioni da riprodurre insieme, in sequenza o dopo un ritardo specificato. Consulta la sezione sulla Coreografia di più elementi con i set di animazioni per ulteriori informazioni. |
I valutatori indicano al sistema di animazione delle proprietà come calcolare i valori per un determinato
proprietà. Prendono i dati sulle tempistiche forniti da un Animator
, i valori di inizio e fine dell'animazione e calcolano i valori animati della proprietà
sulla base di questi dati. Il sistema di animazione delle proprietà fornisce i seguenti valutatori:
Classe/interfaccia | Descrizione |
---|---|
IntEvaluator |
Il valutatore predefinito per calcolare i valori per le proprietà int . |
FloatEvaluator |
Il valutatore predefinito per calcolare i valori per le proprietà float . |
ArgbEvaluator |
Il valutatore predefinito per calcolare i valori delle proprietà del colore rappresentate come valori esadecimali. |
TypeEvaluator |
Un'interfaccia che ti consente di creare un tuo strumento di valutazione. Se stai animando una
che non sia un int , float o un colore,
devi implementare l'interfaccia TypeEvaluator per specificare
per calcolare i valori animati della proprietà dell'oggetto. Puoi anche specificare un TypeEvaluator personalizzato per int , float e colore
se desideri elaborare questi tipi in modo diverso rispetto al comportamento predefinito.
Consulta la sezione sull'utilizzo di un TypeEvaluator per ulteriori informazioni.
informazioni su come scrivere un
valutatore personalizzato. |
Un interpolatore temporale definisce il modo in cui i valori specifici di un'animazione vengono calcolati come
funzione del tempo. Ad esempio, puoi specificare che le animazioni vengano visualizzate linearmente
animazione, vale a dire che l'animazione si sposta per tutto il tempo; in alternativa, puoi specificare le animazioni
per utilizzare il tempo non lineare, ad esempio l'accelerazione all'inizio e la decelerazione al
fine dell'animazione. La tabella 3 descrive gli interpolatori contenuti in android.view.animation
. Se nessuno degli interpolatori forniti è adatto
in base alle tue esigenze, implementa l'interfaccia TimeInterpolator
e creane una personalizzata. Consulta la sezione Utilizzo degli interpolatori per ulteriori informazioni su come scrivere un prompt personalizzato
dell'interpolatore.
Classe/interfaccia | Descrizione |
---|---|
AccelerateDecelerateInterpolator |
Un interpolatore la cui frequenza di cambiamento inizia e termina lentamente ma accelera al centro. |
AccelerateInterpolator |
Un interpolatore il cui tasso di cambiamento inizia lentamente e poi che accelera. |
AnticipateInterpolator |
Un interpolatore il cui cambiamento inizia indietro e si sposta in avanti. |
AnticipateOvershootInterpolator |
Un interpolatore il cui cambiamento inizia all'indietro, si lancia in avanti e si sfora il valore target, per poi tornare al valore finale. |
BounceInterpolator |
Un interpolatore la cui modifica rimbalza alla fine. |
CycleInterpolator |
Un interpolatore la cui animazione si ripete per un determinato numero di cicli. |
DecelerateInterpolator |
Un interpolatore il cui tasso di variazione inizia rapidamente e poi rallenta. |
LinearInterpolator |
Un interpolatore il cui tasso di variazione è costante. |
OvershootInterpolator |
Un interpolatore la cui modifica scorre in avanti e supera l'ultimo valore quindi torna indietro. |
TimeInterpolator |
Un'interfaccia che consente di implementare un interpolatore personalizzato. |
Creazione di animazioni con ValueAnimator
La classe ValueAnimator
ti consente di animare valori di qualche tipo per il
durata di un'animazione specificando un insieme di int
, float
o colore
valori da includere nell'animazione. Ricevi un ValueAnimator
chiamando uno di
ai suoi metodi di fabbrica: ofInt()
, ofFloat()
o ofObject()
. Ad esempio:
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
In questo codice, ValueAnimator
inizia a calcolare i valori dell'attributo
un valore compreso tra 0 e 100 per una durata di 1000 ms, quando viene eseguito il metodo start()
.
Puoi anche specificare un tipo personalizzato da animare procedendo nel seguente modo:
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
In questo codice, ValueAnimator
inizia a calcolare i valori dell'attributo
dell'animazione, tra startPropertyValue
e endPropertyValue
utilizzando
logica fornita da MyTypeEvaluator
per una durata di 1000 ms, quando viene eseguito il metodo start()
.
Puoi utilizzare i valori dell'animazione aggiungendo un parametro
AnimatorUpdateListener
all'oggetto ValueAnimator
, come mostrato
codice seguente:
Kotlin
ValueAnimator.ofObject(...).apply { ... addUpdateListener { updatedAnimation -> // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. textView.translationX = updatedAnimation.animatedValue as Float } ... }
Java
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { // You can use the animated value in a property that uses the // same type as the animation. In this case, you can use the // float value in the translationX property. float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } });
In onAnimationUpdate()
puoi accedere al valore aggiornato dell'animazione e utilizzarlo in una proprietà
una delle tue viste. Per ulteriori informazioni sugli ascoltatori, consulta la sezione su
Ascoltatori di animazioni.
Creazione di animazioni con ObjectAnimator
ObjectAnimator
è una sottoclasse di ValueAnimator
(esaminata nella sezione precedente) e combina i tempi
calcolo del valore e del motore di ValueAnimator
, con la possibilità
animare una proprietà con nome di un oggetto target. In questo modo l'animazione di qualsiasi oggetto è molto più facile,
non è più necessario implementare ValueAnimator.AnimatorUpdateListener
,
perché la proprietà animata si aggiorna automaticamente.
La creazione di un'istanza per un ObjectAnimator
è simile a un ValueAnimator
, ma devi specificare anche l'oggetto e il nome della sua proprietà (come
una stringa) insieme ai valori tra cui eseguire l'animazione:
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Per fare in modo che ObjectAnimator
aggiorni le proprietà
devi effettuare le seguenti operazioni:
- La proprietà dell'oggetto che stai animando deve avere una funzione di impostazione (in caso camel) sotto forma di
set<PropertyName>()
. PoichéObjectAnimator
aggiorna automaticamente la proprietà durante l'animazione, deve potervi accedere con questo metodo del setter. Ad esempio, se il nome della proprietà èfoo
, devi hanno un metodosetFoo()
. Se questo metodo di impostazione non esiste, sono presenti opzioni:- Se disponi dei diritti necessari, aggiungi alla classe il metodo di impostazione.
- Utilizza una classe wrapper che hai i diritti di modifica e che il wrapper riceve con un metodo setter valido e inoltrarlo all'oggetto originale.
- Usa invece il criterio
ValueAnimator
.
- Se specifichi un solo valore per il parametro
values...
in uno dei metodi di fabbricaObjectAnimator
, si presume che sia il valore finale del parametro l'animazione. Pertanto, la proprietà dell'oggetto che stai animando deve avere una funzione getter utilizzato per ottenere il valore iniziale dell'animazione. La funzione getter deve essere nel forma diget<PropertyName>()
. Ad esempio, se il nome della proprietà èfoo
, devi avere un metodogetFoo()
. - I metodi getter (se necessario) e setter della proprietà che stai animando devono
operano sullo stesso tipo dei valori iniziale e finale specificati in
ObjectAnimator
. Ad esempio, devi averetargetObject.setPropName(float)
etargetObject.getPropName()
se crei il seguenteObjectAnimator
:ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- A seconda della proprietà o dell'oggetto che stai animando, potresti dover chiamare il metodo
invalidate()
su una vista per forzare lo schermo a ridisegnarsi con il metodo valori animati aggiornati. Puoi farlo nelonAnimationUpdate()
di Google. Ad esempio, l'animazione della proprietà colore di un oggetto Drawable provoca solo l'aggiornamento della schermata quando l'oggetto viene ridisegnato. Tutte le impostazioni di proprietà su View, ad esempiosetAlpha()
esetTranslationX()
invalida correttamente la vista, quindi non è necessario invalidarla quando chiami questi con nuovi valori. Per ulteriori informazioni sugli ascoltatori, consulta la sezione su Ascoltatori di animazioni.
Crea una coreografia di più animazioni con un AnimatorSet
In molti casi, desideri riprodurre un'animazione che dipende dall'avvio o dall'avvio di un'altra animazione.
finiture in cui sono finite. Il sistema Android ti consente di raggruppare le animazioni in un AnimatorSet
, in modo da poter specificare se avviare le animazioni
contemporaneamente, in sequenza o dopo un determinato ritardo. Puoi anche nidificare AnimatorSet
oggetti l'uno all'interno dell'altro.
Il seguente snippet di codice riproduce il seguente Animator
nel seguente modo:
- Riproduce
bounceAnim
. - Riproduce
squashAnim1
,squashAnim2
,stretchAnim1
estretchAnim2
contemporaneamente. - Riproduce
bounceBackAnim
. - Riproduce
fadeAnim
.
Kotlin
val bouncer = AnimatorSet().apply { play(bounceAnim).before(squashAnim1) play(squashAnim1).with(squashAnim2) play(squashAnim1).with(stretchAnim1) play(squashAnim1).with(stretchAnim2) play(bounceBackAnim).after(stretchAnim2) } val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 } AnimatorSet().apply { play(bouncer).before(fadeAnim) start() }
Java
AnimatorSet bouncer = new AnimatorSet(); bouncer.play(bounceAnim).before(squashAnim1); bouncer.play(squashAnim1).with(squashAnim2); bouncer.play(squashAnim1).with(stretchAnim1); bouncer.play(squashAnim1).with(stretchAnim2); bouncer.play(bounceBackAnim).after(stretchAnim2); ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(bouncer).before(fadeAnim); animatorSet.start();
Listener di animazione
Puoi ascoltare gli eventi importanti durante la durata di un'animazione con i listener descritti di seguito.
Animator.AnimatorListener
onAnimationStart()
- Richiamato all'avvio dell'animazione.onAnimationEnd()
- Richiamato al termine dell'animazione.onAnimationRepeat()
: viene chiamato quando l'animazione si ripete.onAnimationCancel()
: viene chiamato quando l'animazione viene annullata. Un'animazione annullata chiama ancheonAnimationEnd()
, indipendentemente da come sono state terminate.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
: viene richiamato in ogni frame dell'animazione. Ascolta questo evento per utilizza i valori calcolati generati daValueAnimator
durante un evento l'animazione. Per utilizzare il valore, esegui una query sull'oggettoValueAnimator
passato all'evento per ottenere il valore animato corrente con il metodogetAnimatedValue()
. In fase di implementazione il listener è obbligatorio se utilizziValueAnimator
.A seconda della proprietà o dell'oggetto che stai animando, potrebbe essere necessario chiamare
invalidate()
su una vista per forzare quell'area dell'elemento per ridisegnarsi con i nuovi valori animati. Ad esempio, l'animazione proprietà color di un oggetto Drawable provoca gli aggiornamenti dello schermo solo quando quell'oggetto ridisegna automaticamente. Tutte le impostazioni delle proprietà su View, comesetAlpha()
esetTranslationX()
invalida la vista correttamente, in modo da non dover invalidare la vista quando chiami questi metodi con nuovi valori.
-
Puoi estendere la classe AnimatorListenerAdapter
anziché
implementare l'interfaccia Animator.AnimatorListener
, se
vuoi implementare tutti i metodi del metodo Animator.AnimatorListener
a riga di comando. La classe AnimatorListenerAdapter
fornisce elementi
le implementazioni dei metodi che puoi scegliere di sostituire.
Ad esempio, il seguente snippet di codice crea un AnimatorListenerAdapter
solo per onAnimationEnd()
callback:
Kotlin
ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply { duration = 250 addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { balls.remove((animation as ObjectAnimator).target) } }) }
Java
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f); fadeAnim.setDuration(250); fadeAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { balls.remove(((ObjectAnimator)animation).getTarget()); }
Anima le modifiche al layout degli oggetti ViewGroup
Il sistema di animazione delle proprietà consente di animare le modifiche agli oggetti ViewGroup nonché un modo semplice per animare gli oggetti View.
Puoi animare le modifiche al layout all'interno di un ViewGroup con il
LayoutTransition
corso. Le viste all'interno di un ViewGroup possono
vedere un'animazione che appare e scompare quando le aggiungi o
rimuovile da un ViewGroup o quando chiami
setVisibility()
metodo con
VISIBLE
, INVISIBLE
o
GONE
. Le viste rimanenti di ViewGroup possono anche
si anima nelle nuove posizioni quando aggiungi o rimuovi visualizzazioni. Puoi definire
le seguenti animazioni in un oggetto LayoutTransition
chiamando il numero setAnimator()
e passando un oggetto Animator
con uno dei
le seguenti costanti LayoutTransition
:
APPEARING
: un flag che indica l'animazione eseguita sugli elementi che vengono visualizzati nel contenitore.CHANGE_APPEARING
: un flag che indica l'animazione eseguita sugli elementi che vengono modificata in seguito alla visualizzazione di un nuovo elemento nel contenitore.DISAPPEARING
: un flag che indica l'animazione eseguita sugli elementi che vengono scomparirà dal contenitore.CHANGE_DISAPPEARING
: un flag che indica l'animazione eseguita sugli elementi che stanno cambiando perché un elemento scompare dal contenitore.
Puoi definire animazioni personalizzate per questi quattro tipi di eventi per personalizzare l'aspetto delle transizioni di layout o indica semplicemente al sistema di animazione di utilizzare le animazioni predefinite.
Per impostare l'attributo android:animateLayoutchanges
su true
per
ViewGroup:
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
L'impostazione di questo attributo su true anima automaticamente le visualizzazioni aggiunte o rimosse dal ViewGroup e le restanti viste in ViewGroup.
Animazione delle modifiche dello stato di visualizzazione utilizzando StateListAnimator
Il corso StateListAnimator
ti consente di definire animatori da eseguire
lo stato di una vista cambia. Questo oggetto si comporta come un wrapper per
Animator
, richiamando l'animazione ogni volta che viene specificato
modifiche allo stato di visualizzazione (ad esempio "premuto" o "attivata").
StateListAnimator
può essere definito in una risorsa XML con un
L'elemento <selector>
e gli elementi <item>
secondari specificati ciascuno
un altro stato di visualizzazione definito dalla classe StateListAnimator
. Ciascuna
<item>
contiene la definizione di un set di animazione della proprietà.
Ad esempio, il seguente file crea un animatore per l'elenco di stati che modifica la scala x e y della vista quando viene premuto:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- the pressed state; increase x and y size to 150% --> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1.5" android:valueType="floatType"/> </set> </item> <!-- the default, non-pressed state; set x and y size to 100% --> <item android:state_pressed="false"> <set> <objectAnimator android:propertyName="scaleX" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:propertyName="scaleY" android:duration="@android:integer/config_shortAnimTime" android:valueTo="1" android:valueType="floatType"/> </set> </item> </selector>
Per allegare l'animatore dell'elenco di stati a una vista, aggiungi
android:stateListAnimator
come segue:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Ora le animazioni definite in animate_scale.xml
vengono utilizzate quando viene
modifiche dello stato.
In alternativa, per assegnare un animatore dell'elenco di stati a una vista nel tuo codice, utilizza il metodo
AnimatorInflater.loadStateListAnimator()
e assegna l'animatore a
la tua visualizzazione con il metodo View.setStateListAnimator()
.
In alternativa, invece di animare le proprietà della vista, puoi riprodurre un'animazione disegnabile tra
modifiche di stato utilizzando AnimatedStateListDrawable
.
Alcuni widget di sistema
Android 5.0 utilizza queste animazioni per impostazione predefinita. L'esempio seguente mostra come
per definire AnimatedStateListDrawable
come risorsa XML:
<!-- res/drawable/myanimstatedrawable.xml --> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- provide a different drawable for each state--> <item android:id="@+id/pressed" android:drawable="@drawable/drawableP" android:state_pressed="true"/> <item android:id="@+id/focused" android:drawable="@drawable/drawableF" android:state_focused="true"/> <item android:id="@id/default" android:drawable="@drawable/drawableD"/> <!-- specify a transition --> <transition android:fromId="@+id/default" android:toId="@+id/pressed"> <animation-list> <item android:duration="15" android:drawable="@drawable/dt1"/> <item android:duration="15" android:drawable="@drawable/dt2"/> ... </animation-list> </transition> ... </animated-selector>
Usa un TypeEvaluator
Se vuoi animare un tipo sconosciuto al sistema Android, puoi crearne uno personalizzato
di valutazione implementando l'interfaccia TypeEvaluator
. I tipi che
noti dal sistema Android sono int
, float
o un colore, che sono
supportato dai tipi IntEvaluator
, FloatEvaluator
e ArgbEvaluator
valutatori.
Esiste un solo metodo da implementare nelle TypeEvaluator
dell'interfaccia, il metodo evaluate()
. Ciò consente
l'animatore che stai utilizzando per restituire un valore appropriato per la tua proprietà animata nel campo
punto corrente dell'animazione. Il corso FloatEvaluator
dimostra
come fare:
Kotlin
private class FloatEvaluator : TypeEvaluator<Any> { override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any { return (startValue as Number).toFloat().let { startFloat -> startFloat + fraction * ((endValue as Number).toFloat() - startFloat) } } }
Java
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
Nota: quando viene eseguito ValueAnimator
(o ObjectAnimator
), calcola una frazione attuale trascorsa del
dell'animazione (un valore compreso tra 0 e 1), quindi ne calcola una versione interpolata a seconda
sull'interpolatore che stai utilizzando. La frazione interpolata è quella che TypeEvaluator
riceve tramite il parametro fraction
, quindi
non devono tenere conto dell'interpolatore per il calcolo dei valori animati.
Utilizzare gli interpolatori
Un interpolatore definisce in che modo valori specifici in un'animazione vengono calcolati come funzione di nel tempo. Ad esempio, puoi specificare che le animazioni vengano visualizzate linearmente in tutta l'animazione, il che significa che l'animazione si muove in modo uniforme per tutto il tempo, oppure puoi specificare animazioni da utilizzare tempo non lineare, ad esempio utilizzando l'accelerazione o la decelerazione all'inizio o alla fine del l'animazione.
Gli interpolatori nel sistema di animazione ricevono una frazione dagli elementi animati che rappresentano
tempo trascorso dell'animazione. Gli interpolatori modificano questa frazione in modo che coincida con il tipo di
animazione che mira a fornire. Il sistema Android fornisce una serie di interpolatori comuni
android.view.animation package
. Se nessuna di queste opzioni soddisfa le tue
necessarie, puoi implementare l'interfaccia TimeInterpolator
e creare
personali.
Ad esempio, di seguito viene confrontato il modo in cui l'interpolatore predefinito AccelerateDecelerateInterpolator
e LinearInterpolator
calcolano le frazioni interpolate.
Il valore LinearInterpolator
non ha alcun effetto sulla frazione trascorsa. L'elemento AccelerateDecelerateInterpolator
si avvia nell'animazione e
ne rallenta l'uscita. I seguenti metodi definiscono la logica per questi interpolatori:
AccelerateDecelerateInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f
Java
@Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }
LinearInterpolator
Kotlin
override fun getInterpolation(input: Float): Float = input
Java
@Override public float getInterpolation(float input) { return input; }
La tabella seguente rappresenta i valori approssimativi calcolati in base a questi per un'animazione di durata 1000 ms:
ms trascorsi | Frazione passata/Frazione interpolata (Lineare) | Frazione interpolata (accelerazione/decelerazione) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,8 |
800 | 0,8 | 0,9 |
1000 | 1 | 1 |
Come mostrato nella tabella, LinearInterpolator
cambia i valori.
alla stessa velocità, 0,2 ogni 200 ms superati. AccelerateDecelerateInterpolator
cambia i valori più velocemente di LinearInterpolator
tra 200 ms e 600 ms e più lentamente tra 600 ms e
1000ms.
Specificare i fotogrammi chiave
Un oggetto Keyframe
è composto da una coppia tempo/valore che ti consente di definire
uno stato specifico nel momento specifico di un'animazione. Ogni fotogramma chiave può avere anche il suo
interpolatore per controllare il comportamento dell'animazione nell'intervallo tra i precedenti
il tempo e il tempo del fotogramma chiave.
Per creare un'istanza di un oggetto Keyframe
, devi utilizzare uno dei deployment
ofInt()
, ofFloat()
o ofObject()
per ottenere il tipo appropriato di Keyframe
. Quindi richiami
il metodo di fabbrica ofKeyframe()
per
ottenere un oggetto PropertyValuesHolder
. Una volta ottenuto l'oggetto, puoi
ottenere un animatore passando l'oggetto PropertyValuesHolder
e
l'oggetto da animare. Il seguente snippet di codice mostra come eseguire questa operazione:
Kotlin
val kf0 = Keyframe.ofFloat(0f, 0f) val kf1 = Keyframe.ofFloat(.5f, 360f) val kf2 = Keyframe.ofFloat(1f, 0f) val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2) ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply { duration = 5000 }
Java
Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation); rotationAnim.setDuration(5000);
Anima le visualizzazioni
Il sistema di animazione delle proprietà consente un'animazione semplificata degli oggetti View e delle offerte alcuni vantaggi rispetto al sistema di animazione di visualizzazione. La vista il sistema di animazione ha trasformato gli oggetti View modificando il modo in cui erano stati disegnati. Questo è stato gestite nel contenitore di ogni vista, perché la vista stessa non aveva proprietà da manipolare. Di conseguenza, la visualizzazione è stata animata, ma non ha causato modifiche all'oggetto View stesso. Questo comporta un comportamento come un oggetto ancora esistente nella sua posizione originale, anche se era in un punto diverso dello schermo. In Android 3.0, le nuove proprietà e le Per eliminare questo svantaggio sono stati aggiunti i metodi getter e setter.
Il sistema di animazione della proprietà
puoi animare le viste sullo schermo modificando le proprietà effettive negli oggetti View. Nella
in più, le visualizzazioni chiamano anche automaticamente invalidate()
per aggiornare la schermata ogni volta che ne vengono modificate le proprietà. Le nuove proprietà nella classe View
che facilitano le animazioni delle proprietà sono:
translationX
etranslationY
: queste proprietà controllano dove La vista si trova sotto forma di delta dal lato sinistro e le coordinate superiori, impostate dal layout. containerizzato.rotation
,rotationX
erotationY
: queste proprietà controlla la rotazione in 2D (proprietàrotation
) e in 3D intorno al punto pivot.scaleX
escaleY
: queste proprietà controllano la scalabilità 2D di una Vista attorno al punto pivot.pivotX
epivotY
: queste proprietà controllano la posizione delle punto pivot attorno al quale avvengono le trasformazioni di rotazione e scala. Per impostazione predefinita, si trova al centro dell'oggetto.x
ey
: si tratta di semplici proprietà di utilità per descrivere posizione finale della vista nel relativo contenitore, come una somma dei valori "sinistra" e "in alto" e traslazione X e traslazioneY.alpha
: rappresenta la trasparenza alfa nella vista. Questo valore è 1 (opaco) per impostazione predefinita, con il valore 0 che rappresenta la massima trasparenza (non visibile).
Per animare una proprietà di un oggetto View, come il colore o il valore di rotazione, è sufficiente devi creare un animatore della proprietà e specificare la proprietà Vista che vuoi si anima. Ad esempio:
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Per ulteriori informazioni sulla creazione di animatori, consulta le sezioni sull'animazione con ValueAnimator e ObjectAnimator.
Creazione di animazioni con ViewPropertyAnimator
L'elemento ViewPropertyAnimator
offre un modo semplice per animare diversi
proprietà di un View
in parallelo, utilizzando un'unica proprietà Animator
sottostante
. Si comporta in modo molto simile a un ObjectAnimator
, perché modifica
valori effettivi delle proprietà della vista, ma è più efficiente quando si animano molte proprietà
una volta sola. Inoltre, il codice per usare ViewPropertyAnimator
è molto
più concisi e facili da leggere. I seguenti snippet di codice mostrano le differenze nell'utilizzo di più
ObjectAnimator
oggetti, un singolo
ObjectAnimator
e ViewPropertyAnimator
quando
animando contemporaneamente le proprietà x
e y
di una vista.
Più oggetti ObjectAnimator
Kotlin
val animX = ObjectAnimator.ofFloat(myView, "x", 50f) val animY = ObjectAnimator.ofFloat(myView, "y", 100f) AnimatorSet().apply { playTogether(animX, animY) start() }
Java
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f); ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f); AnimatorSet animSetXY = new AnimatorSet(); animSetXY.playTogether(animX, animY); animSetXY.start();
Un ObjectAnimator
Kotlin
val pvhX = PropertyValuesHolder.ofFloat("x", 50f) val pvhY = PropertyValuesHolder.ofFloat("y", 100f) ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()
Java
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f); ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();
ViewPropertyAnimator
Kotlin
myView.animate().x(50f).y(100f)
Java
myView.animate().x(50f).y(100f);
Per informazioni più dettagliate su ViewPropertyAnimator
, consulta gli sviluppatori Android corrispondenti
blog
post.
Dichiara le animazioni in XML
Il sistema di animazione delle proprietà ti consente di dichiarare le animazioni delle proprietà tramite XML in modo programmatico. Se definisci le animazioni in XML, puoi riutilizzarle facilmente in più attività e modificare più facilmente la sequenza di animazione.
Per distinguere i file di animazione che utilizzano le API di animazione della nuova proprietà da quelli che utilizzano
framework precedente per la visualizzazione di animazioni,
a partire da Android 3.1, devi salvare i file XML per le animazioni delle proprietà nella directory res/animator/
.
Le seguenti classi di animazione delle proprietà supportano la dichiarazione XML con il seguenti tag XML:
ValueAnimator
-<animator>
ObjectAnimator
-<objectAnimator>
AnimatorSet
-<set>
Per trovare gli attributi che puoi utilizzare nella dichiarazione XML, consulta la sezione Animazione Google Cloud. L'esempio seguente riproduce i due insiemi di animazioni di oggetti in sequenza, con il primo set nidificato che riproduce due animazioni di oggetti insieme:
<set android:ordering="sequentially"> <set> <objectAnimator android:propertyName="x" android:duration="500" android:valueTo="400" android:valueType="intType"/> <objectAnimator android:propertyName="y" android:duration="500" android:valueTo="300" android:valueType="intType"/> </set> <objectAnimator android:propertyName="alpha" android:duration="500" android:valueTo="1f"/> </set>
Per eseguire questa animazione, devi gonfiare le risorse XML del tuo codice impostandole su un oggetto AnimatorSet
, quindi impostare gli oggetti di destinazione per tutte le animazioni
prima di iniziare il set di animazioni. La chiamata a setTarget()
consente di impostare un singolo oggetto di destinazione per tutti gli elementi secondari di AnimatorSet
per comodità. Il seguente codice mostra come fare:
Kotlin
(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply { setTarget(myObject) start() }
Java
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.animator.property_animator); set.setTarget(myObject); set.start();
Puoi anche dichiarare un ValueAnimator
in XML, come
come mostrato nell'esempio seguente:
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Per usare l'elemento ValueAnimator
precedente nel codice,
devi gonfiare l'oggetto, aggiungi un
AnimatorUpdateListener
,
ottenere il valore aggiornato dell'animazione e utilizzarlo in una proprietà di una delle viste,
come mostrato nel seguente codice:
Kotlin
(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply { addUpdateListener { updatedAnimation -> textView.translationX = updatedAnimation.animatedValue as Float } start() }
Java
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator); xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator updatedAnimation) { float animatedValue = (float)updatedAnimation.getAnimatedValue(); textView.setTranslationX(animatedValue); } }); xmlAnimator.start();
Per informazioni sulla sintassi XML per la definizione delle animazioni delle proprietà, consulta Animazione Google Cloud .
Potenziali effetti sulle prestazioni dell'interfaccia utente
Gli elementi di animazione che aggiornano l'interfaccia utente comportano un lavoro di rendering aggiuntivo per ogni frame in eseguire l'animazione. Per questo motivo, l'uso di animazioni che consumano molte risorse possono influire negativamente sulle prestazioni dell'app.
Il lavoro necessario per animare l'UI viene aggiunto allo fase di animazione di della pipeline di rendering. Puoi scoprire se le animazioni influiscono delle prestazioni della tua app attivando il rendering GPU profilo e monitorando la fase dell'animazione. Per ulteriori informazioni, consulta la sezione Rendering GPU del profilo procedura dettagliata.