Il sistema di animazione delle proprietà è un framework solido che consente di animare quasi tutto. Puoi definire un'animazione per modificare qualsiasi proprietà dell'oggetto nel tempo, che attiri o meno lo schermo. Un'animazione di proprietà modifica il valore di una proprietà (un campo in un oggetto) in un periodo di tempo specificato. 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 durata 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 ripetizioni: puoi specificare se un'animazione deve ripetersi quando raggiunge la fine di una durata e quante volte ripetere l'animazione. Puoi anche specificare se vuoi che l'animazione venga riprodotta in senso inverso. 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. Il valore predefinito è impostato su aggiornamento ogni 10 ms, ma la velocità con cui l'applicazione può aggiornare i frame dipende in ultima analisi dall'utilizzo complessivo del sistema e dalla velocità con cui il sistema può gestire il timer sottostante.
Per vedere un esempio completo di animazione delle proprietà, consulta la classe ChangeColor
nell'esempio CustomTransition su GitHub.
Come funziona l'animazione della proprietà
Innanzitutto, vediamo come funziona un'animazione con un semplice esempio. La Figura 1 mostra 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, ovvero la frequenza di aggiornamento predefinita dei frame, l'oggetto si sposta orizzontalmente 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, il che significa che
l'oggetto si muove a velocità costante.

Figura 1. Esempio di animazione lineare
Puoi anche specificare le animazioni per avere un'interpolazione non lineare. La Figura 2 mostra un oggetto ipotetico che accelera all'inizio dell'animazione e decelera alla 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 mostrato nella Figura 2, la distanza percorsa all'inizio e alla fine dell'animazione è inferiore rispetto a quella percorsa al centro.

Figura 2. Esempio di animazione non lineare
Diamo un'occhiata dettagliata a come i componenti importanti del sistema di animazione delle proprietà calcolano animazioni come quelle illustrate sopra. La Figura 3 mostra il funzionamento delle classi principali tra di loro.

Figura 3. Come vengono calcolate le animazioni
L'oggetto ValueAnimator
tiene traccia della temporizzazione dell'animazione, ad esempio del tempo di esecuzione dell'animazione e del valore corrente della proprietà che viene animata.
ValueAnimator
incapsula un TimeInterpolator
, che definisce l'interpolazione dell'animazione, e un TypeEvaluator
, che definisce come calcolare i valori per la proprietà animata. Ad esempio, nella Figura 2, il TimeInterpolator
utilizzato è AccelerateDecelerateInterpolator
e il 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 di tempo trascorso tra 0 e 1, in base alla durata dell'animazione e al tempo trascorso. La
frazione di tempo trascorsa rappresenta la percentuale di tempo in cui l'animazione è stata completata, 0 significa 0%
e 1 significa 100%. Ad esempio, nella Figura 1, la frazione di tempo trascorsa a t = 10 ms è 0,25
perché la durata totale è t = 40 ms.
Quando ValueAnimator
ha terminato di calcolare una frazione di tempo trascorso, chiama TimeInterpolator
attualmente impostato per calcolare una 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, poiché l'animazione accelera lentamente, la frazione interpolata, circa 0,15, è inferiore alla frazione trascorsa, 0,25, a t = 10 ms. Nella Figura 1, la frazione interpolata è sempre uguale alla frazione trascorsa.
Quando viene calcolata la frazione interpolata, ValueAnimator
chiama TypeEvaluator
appropriato per calcolare il valore della proprietà di cui stai animando, in base alla frazione interpolata, al valore iniziale e al 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 delle visualizzazioni offre la possibilità di animare solo gli oggetti View
, quindi se vuoi animare oggetti diversi da View
, devi implementare il tuo codice. Il sistema di animazione delle visualizzazioni è limitato anche dal fatto che espone solo alcuni aspetti di un oggetto View
da animare, ad esempio la scala e la rotazione di una visualizzazione, ma non il colore di sfondo.
Un altro svantaggio del sistema di animazione della visualizzazione è che modificava solo la posizione in cui veniva disegnata la visualizzazione e non la visualizzazione stessa. Ad esempio, se hai animato un pulsante in modo che si muova sullo schermo, il pulsante viene disegnato correttamente, ma la posizione effettiva in cui puoi fare clic sul pulsante non cambia, quindi devi implementare la tua logica per gestire questo problema.
Con il sistema di animazione delle proprietà, questi vincoli vengono rimossi completamente e puoi animare qualsiasi proprietà di qualsiasi oggetto (viste e non) e l'oggetto stesso viene effettivamente modificato. Il sistema di animazione delle proprietà è anche più solido nel modo in cui esegue l'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.
Tuttavia, il sistema di animazione della visualizzazione richiede meno tempo per la configurazione e meno codice da scrivere. Se l'animazione di visualizzazione 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 situazioni diverse, qualora si presenti il 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 tabelle seguenti descrivono i componenti principali del sistema di animazione delle proprietà.
La classe Animator
fornisce la struttura di base per creare animazioni. In genere, non utilizzi questa classe direttamente perché fornisce solo funzionalità minime che devono essere estese per supportare completamente l'animazione dei valori. I seguenti
sottoclassi estendono Animator
:
Tabella 1. Animatori
Classe | Descrizione |
---|---|
ValueAnimator |
Il motore di temporizzazione principale per l'animazione delle proprietà che calcola anche i valori della proprietà da animare. Include tutte le funzionalità di base che calcolano 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. Per ulteriori informazioni, consulta la sezione su
Animazione con ValueAnimator. |
ObjectAnimator |
Una sottoclasse di ValueAnimator che consente di impostare un oggetto
di destinazione e una proprietà dell'oggetto da animare. Questa classe aggiorna la proprietà di conseguenza quando calcola un nuovo valore per l'animazione. Vuoi utilizzare
ObjectAnimator la maggior parte delle volte,
perché rende molto più semplice 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 |
Offre un meccanismo per raggruppare le animazioni in modo che vengano eseguite relazione tra loro. Puoi impostare le animazioni in modo che vengano riprodotte insieme, in sequenza o dopo un ritardo specificato. Per ulteriori informazioni, consulta la sezione Coreografia di più animazioni con gli insiemi di animatori. |
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:
Tabella 2. 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 per le proprietà di colore rappresentate come valori esadecimali. |
TypeEvaluator |
Un'interfaccia che ti consente di creare un tuo strumento di valutazione. Se stai animando
una proprietà oggetto che non è int , float o un colore,
devi implementare l'interfaccia TypeEvaluator per specificare come
calcolare i valori animati della proprietà oggetto. Puoi anche specificare un TypeEvaluator personalizzato per i valori int , float e colore se vuoi elaborare questi tipi in modo diverso rispetto al comportamento predefinito.
Per ulteriori informazioni su come scrivere un valutatore personalizzato, consulta la sezione Utilizzo di un valutatore di tipo. |
Un interpolatore temporale definisce in che modo vengono calcolati valori specifici in un'animazione come funzione del tempo. Ad esempio, puoi specificare che le animazioni si verifichino in modo lineare nell'intera animazione, ovvero che si muovano in modo uniforme per tutto il tempo, oppure puoi specificare che le animazioni utilizzino un tempo non lineare, ad esempio accelerando all'inizio e decelerando alla 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.
Tabella 3. Interpolatori
Classe/interfaccia | Descrizione |
---|---|
AccelerateDecelerateInterpolator |
Un interpolatore la cui frequenza di cambiamento inizia e termina lentamente ma accelera al centro. |
AccelerateInterpolator |
Un interpolatore la cui velocità di variazione inizia lentamente e poi accelera. |
AnticipateInterpolator |
Un interpolatore la cui variazione inizia all'indietro e poi si sposta in avanti. |
AnticipateOvershootInterpolator |
Un interpolatore il cui cambiamento inizia all'indietro, si lancia in avanti e supera il valore target, per poi tornare al valore finale. |
BounceInterpolator |
Un interpolatore la cui variazione 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 si sposta in avanti e supera l'ultimo valore, poi rientra. |
TimeInterpolator |
Un'interfaccia che consente di implementare un interpolatore personalizzato. |
Creare animazioni utilizzando ValueAnimator
La classe ValueAnimator
consente di animare valori di un determinato tipo per la durata di un'animazione specificando un insieme di valori int
, float
o di colore da animare. Puoi ottenere un ValueAnimator
chiamando uno dei 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'animazione, compresi 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.
Creare animazioni utilizzando ObjectAnimator
ObjectAnimator
è una sottoclasse di ValueAnimator
(discussa nella sezione precedente) e combina il motore di temporizzazione e il calcolo del valore di ValueAnimator
con la possibilità di animare una proprietà denominata 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.
L'inizializzazione di un ObjectAnimator
è simile a quella di un ValueAnimator
, ma devi specificare anche l'oggetto e il nome della relativa proprietà (come 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 CamelCase) 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, hai tre opzioni:- Aggiungi il metodo setter alla classe se disponi dei diritti necessari.
- Utilizza una classe wrapper di cui disponi dei diritti di modifica e che il wrapper riceva il 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 dell'animazione. Pertanto, la proprietà dell'oggetto che stai animando deve avere una funzione di getter utilizzata per ottenere il valore iniziale dell'animazione. La funzione di getter deve avere il formatoget<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 operare sullo stesso tipo dei valori iniziale e finale specificati per
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à color di un oggetto Drawable provoca aggiornamenti della schermata solo quando l'oggetto si ridisegna. 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 relativa ai ascoltatori di animazione.
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 avviarle contemporaneamente, in sequenza o dopo un ritardo specificato. 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. - Riproduci
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()
- Viene chiamato all'avvio dell'animazione.onAnimationEnd()
- Viene chiamato 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 utilizzare i valori calcolati generati daValueAnimator
durante un 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 della proprietà colore di un oggetto Drawable causa aggiornamenti sullo schermo solo quando l'oggetto si ridisegna. Tutti gli attributi di impostazione della visualizzazione, comesetAlpha()
esetTranslationX()
, invalidano correttamente la visualizzazione, quindi non è necessario invalidarla quando chiami questi metodi con nuovi valori.
-
Se non vuoi implementare tutti i metodi dell'interfaccia Animator.AnimatorListener
, puoi estendere la classe AnimatorListenerAdapter
anziché implementare l'interfaccia Animator.AnimatorListener
. 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 visualizzazioni all'interno di un ViewGroup possono essere visualizzate e nascoste tramite un'animazione quando le aggiungi o le rimuovi da un ViewGroup o quando chiami il metodo setVisibility()
di una visualizzazione 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 che viene eseguita sugli elementi visualizzati nel contenitore.CHANGE_APPEARING
: un flag che indica l'animazione che viene eseguita sugli elementi in fase di modifica a causa della 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 che viene eseguita sugli elementi che cambiano a causa della scomparsa di un elemento dal contenitore.
Puoi definire le tue animazioni personalizzate per questi quattro tipi di eventi per personalizzare l'aspetto delle transizioni del layout o semplicemente indicare 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.
Animare le modifiche dello stato della 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:
res/xml/animate_scale.xml
<?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 cambia lo stato di questo pulsante.
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, anziché animare le proprietà della visualizzazione, puoi riprodurre un'animazione drawable tra le modifiche di stato utilizzando AnimatedStateListDrawable
.
Alcuni widget di sistema
Android 5.0 utilizza queste animazioni per impostazione predefinita. L'esempio seguente mostra come
definire un 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 creare il tuo valutatore implementando l'interfaccia TypeEvaluator
. I tipi conosciuti dal sistema Android sono int
, float
o un colore, supportati dagli valutatori di tipo IntEvaluator
, FloatEvaluator
e ArgbEvaluator
.
Esiste un solo metodo da implementare nell'interfaccia TypeEvaluator
, ovvero 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. La classe FloatEvaluator
mostra come eseguire questa operazione:
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
), viene calcolata una frazione corrente dell'animazione trascorsa (un valore compreso tra 0 e 1) e poi una versione interpolata in base all'interpolatore utilizzato. La frazione interpolata è ciò che TypeEvaluator
riceve tramite il parametro fraction
, quindi non devi tenere conto dell'interpolatore durante 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 un insieme di interpolatori comuni nel
android.view.animation package
. Se nessuna di queste soddisfa le tue esigenze, puoi implementare l'interfaccia TimeInterpolator
e crearne una personalizzata.
Di seguito è riportato un esempio di come 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 di 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 (Accelera/Rallenta) |
---|---|---|
0 | 0 | 0 |
200 | 0,2 | 0,1 |
400 | 0,4 | 0,345 |
600 | 0,6 | 0,654 |
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
modifica i valori più velocemente di LinearInterpolator
tra 200 ms e 600 ms e più lentamente tra 600 ms e
1000 ms.
Specificare i fotogrammi chiave
Un oggetto Keyframe
è costituito da una coppia di tempo/valore che consente di definire un determinato stato in un momento specifico di un'animazione. Ogni fotogramma chiave può anche avere il proprio interpolatore per controllare il comportamento dell'animazione nell'intervallo tra il tempo del fotogramma chiave precedente e quello di questo fotogramma chiave.
Per creare un'istanza di un oggetto Keyframe
, devi utilizzare uno dei metodi di fabbrica ofInt()
, ofFloat()
o ofObject()
per ottenere il tipo appropriato di Keyframe
. Quindi chiami 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 di semplificare l'animazione degli oggetti View e offre alcuni vantaggi rispetto al sistema di animazione delle visualizzazioni. La vista il sistema di animazione ha trasformato gli oggetti View modificando il modo in cui erano stati disegnati. Questo veniva gestito nel contenitore di ogni visualizzazione, perché la visualizzazione stessa non aveva proprietà da manipolare. Di conseguenza, la visualizzazione è stata animata, ma non ha causato alcuna modifica nell'oggetto View stesso. Questo ha comportato un comportamento come un oggetto ancora esistente nella sua posizione originale, anche se è stato disegnato in una posizione diversa sullo 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 la posizione della vista come delta dalle coordinate sinistra e superiore impostate dal contenitore layout.rotation
,rotationX
erotationY
: queste proprietà controllano la rotazione in 2D (proprietàrotation
) e in 3D attorno al punto di rotazione.scaleX
escaleY
: queste proprietà controllano la scalatura 2D di una vista attorno al suo punto di rotazione.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. Per impostazione predefinita, questo valore è 1 (opaco), mentre un valore di 0 indica la massima trasparenza (non visibile).
Per animare una proprietà di un oggetto View, ad esempio il colore o il valore di rotazione, devi solo creare un animatore di proprietà e specificare la proprietà View da animare. 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 l'utilizzo di ViewPropertyAnimator
è molto più conciso e facile da leggere. Gli snippet di codice seguenti mostrano le differenze nell'utilizzo di più oggetti ObjectAnimator
, un singolo ObjectAnimator
e ViewPropertyAnimator
quando si animano contemporaneamente le proprietà x
e y
di una visualizzazione.
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 nuove API di animazione delle proprietà da quelli che utilizzano il framework animazione della vista precedente,
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 sequenzialmente, con il primo insieme nidificato che riproduce contemporaneamente due animazioni di oggetti:
<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 nel codice in un oggetto AnimatorSet
e impostare gli oggetti di destinazione per tutte le animazioni prima di avviare l'insieme di animazioni. Per comodità, la chiamata a setTarget()
imposta un singolo oggetto target per tutti gli elementi secondari di AnimatorSet
. Il seguente codice mostra come eseguire questa operazione:
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 Risorse di animazione.
Potenziali effetti sulle prestazioni dell'interfaccia utente
Gli animatori che aggiornano l'interfaccia utente causano un lavoro di rendering aggiuntivo per ogni frame in cui viene eseguita l'animazione. Per questo motivo, l'utilizzo di animazioni che richiedono molte risorse può influire negativamente sul rendimento della tua app.
Il lavoro necessario per animare l'interfaccia utente viene aggiunto alla fase di animazione della pipeline di rendering. Per scoprire se le animazioni influiscono sulle prestazioni della tua app, attiva Profila il rendering GPU e monitora la fase di animazione. Per ulteriori informazioni, consulta la sezione Rendering GPU del profilo procedura dettagliata.