Crea un'animazione di transizione personalizzata

Prova la funzionalità Scrivi
Jetpack Compose è il toolkit per l'interfaccia utente consigliato per Android. Scopri come aggiungere animazioni in Scrivi.

Una transizione personalizzata ti consente di creare un'animazione non disponibile in nessuna delle classi di transizione predefinite. Ad esempio, puoi definire una transizione personalizzata che imposti su grigio il colore di primo piano del testo e dei campi di immissione per indicare che i campi sono disattivati nella nuova schermata. Questo tipo di modifica consente agli utenti di vedere i campi che hai disattivato.

Una transizione personalizzata, come uno dei tipi di transizione integrati, applica le animazioni alle visualizzazioni secondarie sia della scena iniziale che di quella finale. Tuttavia, a differenza dei tipi di transizione integrati, devi fornire il codice che acquisisce i valori delle proprietà e genera le animazioni. Potresti anche definire un sottoinsieme di visualizzazioni target per l'animazione.

Questa pagina spiega come acquisire i valori delle proprietà e generare animazioni per creare transizioni personalizzate.

Espandere la classe Transizione

Per creare una transizione personalizzata, aggiungi al progetto una classe che estenda la classe Transition e sostituisca le funzioni mostrate nel seguente snippet:

Kotlin

class CustomTransition : Transition() {

    override fun captureStartValues(transitionValues: TransitionValues) {}

    override fun captureEndValues(transitionValues: TransitionValues) {}

    override fun createAnimator(
        sceneRoot: ViewGroup,
        startValues: TransitionValues?,
        endValues: TransitionValues?
    ): Animator? {}

}

Java

public class CustomTransition extends Transition {

    @Override
    public void captureStartValues(TransitionValues values) {}

    @Override
    public void captureEndValues(TransitionValues values) {}

    @Override
    public Animator createAnimator(ViewGroup sceneRoot,
                                   TransitionValues startValues,
                                   TransitionValues endValues) {}
}

Le sezioni seguenti spiegano come eseguire l'override di queste funzioni.

Acquisisci i valori delle proprietà della visualizzazione

Le animazioni di transizione utilizzano il sistema di animazione delle proprietà descritto in Panoramica dell'animazione delle proprietà. Le animazioni delle proprietà modificano una proprietà della vista da un valore iniziale a un valore finale in un determinato periodo di tempo, pertanto il framework deve avere sia i valori iniziale e finale della proprietà per creare l'animazione.

Tuttavia, un'animazione della proprietà di solito richiede solo un piccolo sottoinsieme di tutti i valori della proprietà della visualizzazione. Ad esempio, un'animazione di colore richiede valori della proprietà di colore, mentre un'animazione di movimento richiede valori della proprietà di posizione. Poiché i valori delle proprietà necessari per un'animazione sono specifici di una transizione, il framework delle transizioni non fornisce ogni valore della proprietà a una transizione. Il framework invoca invece funzioni di callback che consentono di eseguire una transizione per acquisire solo i valori delle proprietà di cui ha bisogno e memorizzarli nel framework.

Acquisisci i valori iniziali

Per passare i valori della visualizzazione iniziale al framework, implementa la funzione captureStartValues(transitionValues). Il framework chiama questa funzione per ogni visualizzazione nella scena iniziale. L'argomento della funzione è un oggetto TransitionValues che contiene un riferimento alla vista e un'istanza Map in cui puoi memorizzare i valori della vista che ti interessano. Nell'implementazione, recupera questi valori delle proprietà e riassegnali al framework archiviandoli nella mappa.

Per assicurarti che la chiave per un valore della proprietà non entri in conflitto con altre chiaviTransitionValues, utilizza il seguente schema di denominazione:

package_name:transition_name:property_name

Lo snippet seguente mostra un'implementazione della funzione captureStartValues():

Kotlin

class CustomTransition : Transition() {

    // Define a key for storing a property value in
    // TransitionValues.values with the syntax
    // package_name:transition_class:property_name to avoid collisions
    private val PROPNAME_BACKGROUND = "com.example.android.customtransition:CustomTransition:background"

    override fun captureStartValues(transitionValues: TransitionValues) {
        // Call the convenience method captureValues
        captureValues(transitionValues)
    }

    // For the view in transitionValues.view, get the values you
    // want and put them in transitionValues.values
    private fun captureValues(transitionValues: TransitionValues) {
        // Get a reference to the view
        val view = transitionValues.view
        // Store its background property in the values map
        transitionValues.values[PROPNAME_BACKGROUND] = view.background
    }

    ...

}

Java

public class CustomTransition extends Transition {

    // Define a key for storing a property value in
    // TransitionValues.values with the syntax
    // package_name:transition_class:property_name to avoid collisions
    private static final String PROPNAME_BACKGROUND =
            "com.example.android.customtransition:CustomTransition:background";

    @Override
    public void captureStartValues(TransitionValues transitionValues) {
        // Call the convenience method captureValues
        captureValues(transitionValues);
    }


    // For the view in transitionValues.view, get the values you
    // want and put them in transitionValues.values
    private void captureValues(TransitionValues transitionValues) {
        // Get a reference to the view
        View view = transitionValues.view;
        // Store its background property in the values map
        transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground());
    }
    ...
}

Acquisisci i valori finali

Il framework chiama la funzione captureEndValues(TransitionValues) una volta per ogni visualizzazione target nella scena finale. Per tutti gli altri aspetti, captureEndValues() funziona come captureStartValues().

Il seguente snippet di codice mostra un'implementazione della funzione captureEndValues():

Kotlin

override fun captureEndValues(transitionValues: TransitionValues) {
    captureValues(transitionValues)
}

Java

@Override
public void captureEndValues(TransitionValues transitionValues) {
    captureValues(transitionValues);
}

In questo esempio, sia le funzioni captureStartValues() sia captureEndValues() invocano captureValues() per recuperare e memorizzare i valori. La proprietà della visualizzazione recuperata da captureValues() è la stessa, ma ha valori diversi nelle scene iniziale e finale. Il framework gestisce mappe separate per gli stati iniziale e finale di una visualizzazione.

Creare un animatore personalizzato

Per animare le modifiche a una visualizzazione tra il suo stato nella scena iniziale e il suo stato nella scena finale, fornisci un animatore sostituendo la funzione createAnimator(). Quando il framework chiama questa funzione, passa la vista principale della scena e gli oggetti TransitionValues che contengono i valori iniziale e finale acquisiti.

Il numero di volte in cui il framework chiama la funzione createAnimator() dipende dalle modifiche che si verificano tra le scene iniziale e finale.

Ad esempio, prendi in considerazione un'animazione di dissolvenza in entrata o in uscita implementata come transizione personalizzata. Se la scena iniziale ha cinque target, di cui due vengono rimossi dalla scena finale, e la scena finale ha i tre target della scena iniziale più un nuovo target, il framework chiama createAnimator() sei volte. Tre delle chiamate animano l'attenuazione e l'aumento dell'intensità dei target che rimangono in entrambi gli oggetti della scena. Altre due chiamate animano lo svanimento dei target rimossi dalla scena finale. Una chiamata anima l'effetto di dissolvenza in entrata del nuovo target nella scena finale.

Per le visualizzazioni target esistenti sia nella scena iniziale che in quella finale, il framework fornisce un oggetto TransitionValues sia per gli argomenti startValues che per endValues. Per le visualizzazioni target esistenti solo nella scena iniziale o finale, il framework fornisce un oggetto TransitionValues per l'argomento corrispondente e null per l'altro.

Per implementare la funzione createAnimator(ViewGroup, TransitionValues, TransitionValues) quando crei una transizione personalizzata, utilizza i valori delle proprietà della vista acquisiti per creare un oggetto Animator e restituirlo al framework. Per un esempio di implementazione, consulta la classe ChangeColor nell'esempio CustomTransition. Per saperne di più sugli animatori delle proprietà, consulta Animazione delle proprietà.

Applicare una transizione personalizzata

Le transizioni personalizzate funzionano come le transizioni integrate. Puoi applicare una transizione personalizzata utilizzando un gestore delle transizioni, come descritto in Applicare una transizione.