Crea un'animazione di transizione personalizzata

Una transizione personalizzata consente di creare un'animazione che non è disponibile in nessuna delle classi di transizione integrate. Ad esempio, puoi definire una transizione personalizzata che imposti il colore di primo piano del testo e dei campi di immissione in grigio, 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 animazioni alle viste secondarie delle scene iniziale e finale. Tuttavia, a differenza dei tipi di transizione integrati, devi fornire il codice che acquisisce i valori delle proprietà e genera animazioni. Potresti anche voler definire un sottoinsieme di visualizzazioni target per l'animazione.

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

Estendere la classe Transizione

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

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 vista

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 periodo di tempo specificato, quindi il framework deve avere entrambi i valori iniziale e finale della proprietà per creare l'animazione.

Tuttavia, di solito l'animazione di una proprietà richiede solo un piccolo sottoinsieme di tutti i valori delle proprietà della vista. Ad esempio, un'animazione a colori richiede valori di proprietà colore, mentre un'animazione di movimento ha bisogno di valori di proprietà posizione. Poiché i valori delle proprietà necessari per un'animazione sono specifici di una transizione, il framework delle transizioni non fornisce tutti i valori delle proprietà per una transizione. Al contrario, il framework richiama funzioni di callback che consentono una transizione per acquisire solo i valori delle proprietà di cui ha bisogno e archiviarli nel framework.

Acquisisci i valori iniziali

Per passare i valori della vista iniziale al framework, implementa la funzione captureStartValues(transitionValues). Il framework chiama questa funzione per ogni visualizzazione della scena iniziale. L'argomento della funzione è un oggetto TransitionValues contenente un riferimento alla vista e un'istanza Map in cui è possibile archiviare i valori della vista desiderati. Nell'implementazione, recupera questi valori delle proprietà e ritrasmettili al framework memorizzandoli nella mappa.

Per garantire che la chiave di un valore di proprietà non sia in conflitto con altre chiavi TransitionValues, 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 di destinazione nella scena finale. Sotto 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, entrambe le funzioni captureStartValues() e captureEndValues() richiamano captureValues() per recuperare e archiviare i valori. La proprietà della vista recuperata da captureValues() è la stessa, ma ha valori diversi nelle scene iniziali e finali. Il framework mantiene mappe separate per lo stato iniziale e finale di una vista.

Creare un animatore personalizzato

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

Il numero di volte in cui il framework chiama la funzione createAnimator() dipende dai cambiamenti che si verificano tra la scena iniziale e quella finale.

Prendiamo ad esempio un'animazione con dissolvenza in uscita o in entrata implementata come transizione personalizzata. Se la scena iniziale ha cinque target, due dei quali vengono rimossi da quella finale e la scena finale include i tre target della scena iniziale più un nuovo target, il framework chiama createAnimator() sei volte. Tre delle chiamate animano la dissolvenza in uscita e in entrata dei target che rimangono in entrambi gli oggetti della scena. Altre due chiamate animano la dissolvenza in uscita dei target rimossi dalla scena finale. Una chiamata anima la dissolvenza in entrata del nuovo target nella scena finale.

Per le viste di destinazione presenti sia nella scena iniziale che nella scena finale, il framework fornisce un oggetto TransitionValues per entrambi gli argomenti startValues e endValues. Per le viste di destinazione che esistono solo nella scena iniziale o finale, il framework fornisce un oggetto TransitionValues per l'argomento corrispondente e null per l'altra.

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

Applica una transizione personalizzata

Le transizioni personalizzate funzionano come quelle integrate. Puoi applicare una transizione personalizzata utilizzando un gestore di transizione, come descritto nella sezione Applicare una transizione.