Panoramica dell'animazione della proprietà

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

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.

Figura 1. Esempio di animazione lineare

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.

Figura 2. Esempio di animazione non lineare

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.

Figura 3. Come vengono calcolate le animazioni

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:

Tabella 1. Animatori

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:

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 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.

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 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 metodo setFoo(). 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 fabbrica ObjectAnimator, 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 di get<PropertyName>(). Ad esempio, se il nome della proprietà è foo, devi avere un metodo getFoo().
  • 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 avere targetObject.setPropName(float) e targetObject.getPropName() se crei il seguente ObjectAnimator:
    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 nel onAnimationUpdate() 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 esempio setAlpha() e setTranslationX() 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:

  1. Riproduce bounceAnim.
  2. Riproduce squashAnim1, squashAnim2, stretchAnim1 e stretchAnim2 contemporaneamente.
  3. Riproduce bounceBackAnim.
  4. 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
  • ValueAnimator.AnimatorUpdateListener
    • onAnimationUpdate(): viene richiamato in ogni frame dell'animazione. Ascolta questo evento per utilizza i valori calcolati generati da ValueAnimator durante un evento l'animazione. Per utilizzare il valore, esegui una query sull'oggetto ValueAnimator passato all'evento per ottenere il valore animato corrente con il metodo getAnimatedValue(). In fase di implementazione il listener è obbligatorio se utilizzi ValueAnimator.

      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, come setAlpha() e setTranslationX() 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:

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 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 e translationY: 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 e rotationY: queste proprietà controlla la rotazione in 2D (proprietà rotation) e in 3D intorno al punto pivot.
  • scaleX e scaleY: queste proprietà controllano la scalabilità 2D di una Vista attorno al punto pivot.
  • pivotX e pivotY: 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 e y: 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:

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.