Créer une animation de transition personnalisée

Une transition personnalisée vous permet de créer une animation qui n'est disponible dans aucune des classes de transition intégrées. Par exemple, vous pouvez définir une transition personnalisée qui transforme la couleur de premier plan du texte et des champs de saisie en gris pour indiquer que ces champs sont désactivés dans le nouvel écran. Ce type de modification permet aux utilisateurs de voir les champs que vous avez désactivés.

Comme l'un des types de transition intégrés, une transition personnalisée applique des animations aux vues enfants des scènes de début et de fin. Toutefois, contrairement aux types de transition intégrés, vous devez fournir le code qui capture les valeurs de propriété et génère des animations. Vous pouvez également définir un sous-ensemble de vues cibles pour votre animation.

Cette page vous explique comment capturer des valeurs de propriété et générer des animations pour créer des transitions personnalisées.

Étendre la classe Transition

Pour créer une transition personnalisée, ajoutez à votre projet une classe qui étend la classe Transition et remplace les fonctions indiquées dans l'extrait de code suivant:

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) {}
}

Les sections suivantes expliquent comment remplacer ces fonctions.

Capturer les valeurs des propriétés de la vue

Les animations de transition utilisent le système d'animation des propriétés décrit dans la section Présentation de l'animation des propriétés. Les animations de propriété modifient une propriété de vue d'une valeur de départ à une valeur de fin sur une période spécifiée. Le framework doit donc disposer à la fois des valeurs de début et de fin de la propriété pour construire l'animation.

Cependant, une animation de propriété n'a généralement besoin que d'un petit sous-ensemble des valeurs de propriété de la vue. Par exemple, une animation de couleur a besoin de valeurs de propriété de couleur, tandis qu'une animation de mouvement nécessite des valeurs de propriété de position. Étant donné que les valeurs de propriété nécessaires pour une animation sont spécifiques à une transition, le framework de transitions ne fournit pas toutes les valeurs de propriété à une transition. Au lieu de cela, le framework appelle des fonctions de rappel qui permettent à une transition de ne capturer que les valeurs de propriété dont il a besoin et de les stocker dans le framework.

Capturer les valeurs de départ

Pour transmettre les valeurs de la vue de départ au framework, implémentez la fonction captureStartValues(transitionValues). Le framework appelle cette fonction pour chaque vue de la scène de départ. L'argument de fonction est un objet TransitionValues qui contient une référence à la vue et une instance Map dans laquelle vous pouvez stocker les valeurs de vue souhaitées. Dans votre implémentation, récupérez ces valeurs de propriété et transmettez-les au framework en les stockant dans la carte.

Pour vous assurer que la clé d'une valeur de propriété n'entre pas en conflit avec d'autres clés TransitionValues, utilisez le schéma de nommage suivant:

package_name:transition_name:property_name

L'extrait de code suivant montre une implémentation de la fonction 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());
    }
    ...
}

Capturer les valeurs de fin

Le framework appelle la fonction captureEndValues(TransitionValues) une fois pour chaque vue cible de la scène de fin. À tous les autres égards, captureEndValues() fonctionne de la même manière que captureStartValues().

L'extrait de code suivant montre une implémentation de la fonction captureEndValues():

Kotlin

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

Java

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

Dans cet exemple, les fonctions captureStartValues() et captureEndValues() appellent toutes deux captureValues() pour récupérer et stocker les valeurs. La propriété de vue récupérée par captureValues() est la même, mais ses valeurs sont différentes dans les scènes de début et de fin. Le framework gère des cartes distinctes pour les états de début et de fin d'une vue.

Créer une animation personnalisée

Pour animer les changements de vue entre son état dans la scène de départ et son état dans la scène de fin, fournissez un animateur en remplaçant la fonction createAnimator(). Lorsque le framework appelle cette fonction, il transmet la vue racine de la scène et les objets TransitionValues contenant les valeurs de début et de fin que vous avez capturées.

Le nombre de fois où le framework appelle la fonction createAnimator() dépend des modifications qui se produisent entre les scènes de début et de fin.

Prenons l'exemple d'une animation de fondu à l'ouverture implémentée en tant que transition personnalisée. Si la scène de départ comporte cinq cibles, dont deux sont supprimées de la scène de fin, et que la scène de fin comporte les trois cibles de la scène de départ et une nouvelle cible, le framework appelle createAnimator() six fois. Trois des appels animent le fondu à la fermeture et à l'ouverture des cibles qui restent dans les deux objets de la scène. Deux autres appels animent la fermeture en fondu des cibles supprimées de la scène finale. Un appel anime le fondu de la nouvelle cible dans la scène de fin.

Pour les vues cibles qui existent à la fois dans les scènes de début et de fin, le framework fournit un objet TransitionValues pour les arguments startValues et endValues. Pour les vues cibles qui n'existent que dans la scène de début ou de fin, le framework fournit un objet TransitionValues pour l'argument correspondant et null pour l'autre.

Pour implémenter la fonction createAnimator(ViewGroup, TransitionValues, TransitionValues) lorsque vous créez une transition personnalisée, utilisez les valeurs des propriétés de vue que vous avez capturées pour créer un objet Animator et le renvoyer au framework. Pour obtenir un exemple d'implémentation, consultez la classe ChangeColor dans l'exemple CustomTransition. Pour en savoir plus sur les animateurs de propriété, consultez Animation de propriétés.

Appliquer une transition personnalisée

Les transitions personnalisées fonctionnent de la même manière que les transitions intégrées. Vous pouvez appliquer une transition personnalisée à l'aide d'un gestionnaire de transition, comme décrit dans Appliquer une transition.