Le système d'animation des propriétés est un framework robuste qui vous permet pour animer presque tout. Vous pouvez définir une animation pour modifier n'importe quelle propriété d'objet au fil du temps, qu'elle s'affiche à l'écran ou non. Une animation de propriété modifie (champ d'un objet) sur une période spécifiée. Pour animer un élément, vous devez spécifier la propriété de l'objet que vous souhaitez animer, comme sa position à l'écran, la durée de l'animation et les valeurs entre lesquelles vous souhaitez l'animer.
Le système d'animation de propriétés vous permet de définir les caractéristiques suivantes d'une animation :
- Durée : vous pouvez spécifier la durée d'une animation. La durée par défaut est de 300 ms.
- Interpolation temporelle: vous pouvez spécifier le mode de calcul des valeurs de la propriété du temps écoulé actuel de l'animation.
- Nombre et comportement de répétition : vous pouvez spécifier si une animation doit être répétée ou non à la fin d'une durée, ainsi que le nombre de répétitions. Vous pouvez également spécifier si vous souhaitez que l'animation soit lue en sens inverse. Si vous le définissez sur "Reverse" (Inverser), l'animation est lue en avant, puis en arrière, de manière répétée, jusqu'à ce que le nombre de répétitions soit atteint.
- Ensembles d'animations: vous pouvez regrouper les animations en ensembles logiques, séquentiellement ou après des retards spécifiés.
- Délai d'actualisation des images: vous pouvez spécifier la fréquence d'actualisation des images de votre animation. La la valeur par défaut est définie sur 10 ms, mais la vitesse à laquelle votre application peut actualiser les images est dépend en fin de compte du niveau d'occupation global du système et de la vitesse à laquelle il peut traiter le minuteur sous-jacent.
Pour voir un exemple complet d'animation de propriété, consultez la classe ChangeColor
dans l'exemple CustomTransition sur GitHub.
Fonctionnement de l'animation de propriété
Commençons par voir comment fonctionne une animation à l'aide d'un exemple simple. La figure 1 représente un objet hypothétique animé avec sa propriété x
, qui représente son emplacement horizontal sur un écran. La durée de l'animation est définie sur 40 ms et la distance à parcourir est de 40 pixels. Tous les 10 ms, qui est la fréquence d'actualisation des images par défaut, l'objet se déplace horizontalement de 10 pixels. Au bout de 40 ms, l'animation s'arrête et l'objet se termine à la position horizontale 40. Il s'agit d'un exemple d'animation avec interpolation linéaire, ce qui signifie que l'objet se déplace à une vitesse constante.
Vous pouvez également spécifier une interpolation non linéaire pour les animations. La figure 2 illustre un objet hypothétique qui accélère au début de l'animation et décélère à la fin de l'animation. L'objet se déplace toujours de 40 pixels en 40 ms, mais de manière non linéaire. Dans commence, l'animation accélère jusqu'à la moitié, puis ralentit jusqu'à la fin de l'animation. Comme le montre la figure 2, la distance parcourue au début et à la fin de l'animation est inférieure à celle du milieu.
Voyons en détail comment les composants importants du système d'animation de propriétés calculent des animations comme celles illustrées ci-dessus. La figure 3 illustre la façon dont les classes principales à collaborer les uns avec les autres.
L'objet ValueAnimator
suit le timing de votre animation, comme la durée de son exécution et la valeur actuelle de la propriété qu'elle anime.
ValueAnimator
encapsule un élément TimeInterpolator
, qui définit l'interpolation de l'animation, et un élément TypeEvaluator
, qui définit le mode de calcul des valeurs de la propriété concernée.
animées. Par exemple, dans la figure 2, le TimeInterpolator
utilisé serait
AccelerateDecelerateInterpolator
et TypeEvaluator
seraient IntEvaluator
.
Pour lancer une animation, créez un ValueAnimator
et attribuez-lui le rôle
les valeurs de début et de fin de la propriété à animer, ainsi que la durée des
l'animation. Lorsque vous appelez start()
, l'animation commence. Pendant toute l'animation, ValueAnimator
calcule une fraction écoulée.
entre 0 et 1, en fonction de la durée de l'animation et du temps écoulé. La
la fraction écoulée représente le pourcentage de temps pendant lequel l'animation s'est terminée, 0 signifiant 0%
et 1 à 100%. Par exemple, sur la figure 1, la fraction écoulée pour t = 10 ms serait de 0,25.
car la durée totale
est t = 40 ms.
Lorsque ValueAnimator
a terminé de calculer une fraction écoulée, il appelle TimeInterpolator
qui est actuellement défini pour calculer une fraction interpolée. Une fraction interpolée mappe la fraction écoulée à une nouvelle
qui prend en compte l'interpolation temporelle définie. Par exemple, dans la figure 2,
Comme l'animation accélère lentement, la fraction interpolée, d'environ 0,15, est inférieure à la
fraction écoulée, 0,25, à t = 10 ms. Dans la figure 1, la fraction interpolée est toujours la même que
la fraction écoulée.
Lorsque la fraction interpolée est calculée, ValueAnimator
appelle le TypeEvaluator
approprié pour calculer la valeur de la propriété que vous animez, en fonction de la fraction interpolée, de la valeur de début et de la valeur de fin de l'animation. Par exemple, dans la figure 2, la fraction interpolée était 0,15 pour t =
10 ms .La valeur de la propriété à ce moment-là est donc 0, 15 × (40 - 0), soit 6.
Différences entre l'animation des propriétés et celle des vues
Le système d'animation de la vue ne permet d'animer que des objets View
. Par conséquent, si vous souhaitez animer des objets autres que View
, vous devez implémenter votre propre code. Le système d'animation de la vue est également limité par le fait qu'il n'expose que quelques aspects d'un objet View
à animer, tels que la mise à l'échelle et la rotation d'une vue, mais pas la couleur d'arrière-plan, par exemple.
Un autre inconvénient du système d'animation des vues est qu'il ne modifiait que l'emplacement La vue a été dessinée, et non la vue elle-même. Par exemple, si vous avez animé un bouton pour déplacer sur l'écran, le bouton s'affiche correctement, mais l'emplacement réel où vous pouvez cliquer ne change pas. Vous devez donc implémenter votre propre logique pour gérer cela.
Avec le système d'animation de propriétés, ces contraintes sont complètement supprimées. Vous pouvez animer n'importe quelle propriété de n'importe quel objet (vues et non-vues), et l'objet lui-même est effectivement modifié. Le système d'animation des propriétés est également plus robuste dans la façon dont il effectue l'animation. De manière générale, vous attribuez des animateurs aux propriétés que vous souhaitez animer, telles que la couleur, la position ou la taille, et vous pouvez définir des aspects de l'animation, tels que l'interpolation et la synchronisation de plusieurs animateurs.
En revanche, le système d'animation des vues prend moins de temps à configurer et nécessite moins de code à écrire. Si l'animation d'affichage accomplit tout ce que vous devez faire, ou si votre code existant fonctionne comme vous le souhaitez, il n'est pas nécessaire d'utiliser le système d'animation des propriétés. Il peut également être judicieux d'utiliser les deux systèmes d'animation pour différentes situations si le cas d'utilisation se présente.
Présentation de l'API
Vous trouverez la plupart des API du système d'animation des propriétés dans android.animation
. Étant donné que le système d'animation de la vue définit déjà de nombreux interpolateurs dans android.view.animation
, vous pouvez également les utiliser dans le système d'animation des propriétés. Les tableaux suivants décrivent les principaux composants du système d'animation des propriétés.
La classe Animator
fournit la structure de base pour créer des animations. Vous n'utilisez généralement pas cette classe directement, car elle ne fournit qu'une fonctionnalité minimale qui doit être étendue pour prendre en charge pleinement l'animation des valeurs. Les sous-classes suivantes étendent Animator
:
Classe | Description |
---|---|
ValueAnimator |
Moteur de minutage principal pour l'animation de propriété, qui calcule également les valeurs de la propriété à animer. Il intègre toutes les fonctionnalités
de base qui permettent de calculer les animations
et contient les détails de minutage de chaque animation, ainsi que des informations sur le fait qu'une
les répétitions de l'animation, les écouteurs qui reçoivent les événements de mise à jour et la possibilité de définir
à évaluer. L'animation des propriétés se compose de deux éléments : le calcul des valeurs animées et le paramétrage de ces valeurs sur l'objet et la propriété animés. ValueAnimator n'effectue pas la deuxième partie. Vous devez donc écouter les mises à jour des valeurs calculées par ValueAnimator et modifier les objets que vous souhaitez animer avec votre propre logique. Pour en savoir plus, consultez la section Animer avec ValueAnimator. |
ObjectAnimator |
Sous-classe de ValueAnimator qui vous permet de définir un objet cible et une propriété d'objet à animer. Cette classe met à jour la propriété en conséquence lorsqu'elle calcule une nouvelle valeur pour l'animation. Vous souhaitez utiliser
ObjectAnimator la plupart du temps,
car il facilite grandement le processus d'animation
des valeurs sur les objets cibles. Toutefois,
vous souhaitez parfois utiliser ValueAnimator directement, car ObjectAnimator comporte quelques restrictions supplémentaires, comme la nécessité d'utiliser des
d'accesseur à l'objet cible. |
AnimatorSet |
Fournit un mécanisme permettant de regrouper des animations afin qu'elles s'exécutent en fonction les unes des autres. Vous pouvez définir des animations à lire ensemble, séquentiellement ou après un délai spécifique. Reportez-vous à la section Choréographie de plusieurs avec Animator Sets. |
Les évaluateurs indiquent au système d'animation de propriété comment calculer les valeurs d'une propriété donnée. Ils prennent les données temporelles fournies par un Animator
.
de début et de fin de l'animation, puis calculer les valeurs animées de la propriété
sur la base de ces données. Le système d'animation de propriétés fournit les évaluateurs suivants :
Classe/Interface | Description |
---|---|
IntEvaluator |
Évaluateur par défaut pour calculer les valeurs des propriétés int . |
FloatEvaluator |
Évaluateur par défaut pour calculer les valeurs des propriétés float . |
ArgbEvaluator |
Évaluateur par défaut pour calculer les valeurs des propriétés de couleur représentées sous forme de valeurs hexadécimales. |
TypeEvaluator |
Interface qui vous permet de créer votre propre évaluateur. Si vous animez une propriété d'objet qui n'est pas une int , une float ou une couleur, vous devez implémenter l'interface TypeEvaluator pour spécifier comment calculer les valeurs animées de la propriété de l'objet. Vous pouvez également spécifier un TypeEvaluator personnalisé pour int , float et une couleur.
si vous souhaitez traiter ces types différemment du comportement par défaut.
Pour en savoir plus, consultez la section sur l'utilisation d'un évaluateur de type.
sur la façon de rédiger un évaluateur personnalisé. |
Un interpolateur de temps définit le mode de calcul des valeurs spécifiques d'une animation
fonction du temps. Par exemple, vous pouvez spécifier que les animations se déroulent de façon linéaire sur l'ensemble
animation, qui signifie qu'elle se déplace uniformément tout au long de la durée, ou vous pouvez spécifier des animations
d'utiliser un temps non linéaire, par exemple, une accélération au début et une diminution au
à la fin de l'animation. Le tableau 3 décrit les interpolateurs contenus dans android.view.animation
. Si aucun des interpolateurs fournis ne convient
selon vos besoins, implémentez l'interface TimeInterpolator
et créez la vôtre. Pour en savoir plus sur l'écriture d'une requête personnalisée, consultez la section Utiliser des interpolateurs.
un interpolateur.
Classe/Interface | Description |
---|---|
AccelerateDecelerateInterpolator |
Interpolateur dont la fréquence de changement commence et se termine lentement, mais accélère au milieu. |
AccelerateInterpolator |
Un interpolateur dont la fréquence de changement commence par être lente, puis s'accélère. |
AnticipateInterpolator |
Un interpolateur dont le changement commence en arrière, puis avance. |
AnticipateOvershootInterpolator |
Un interpolateur dont le changement commence à l'arrière, avance et dépasse la valeur cible, puis revient finalement à la valeur finale. |
BounceInterpolator |
Un interpolateur dont le changement rebondit à la fin. |
CycleInterpolator |
Interpolateur dont l'animation se répète pendant un nombre spécifié de cycles. |
DecelerateInterpolator |
Un interpolateur dont la fréquence de changement démarre rapidement, puis ralentit. |
LinearInterpolator |
Interpolateur dont la fréquence de changement est constante. |
OvershootInterpolator |
un interpolateur dont le changement avance et dépasse la dernière valeur, puis est renvoyée. |
TimeInterpolator |
Interface qui vous permet d'implémenter votre propre interpolateur. |
Animer à l'aide de ValueAnimator
La classe ValueAnimator
vous permet d'animer des valeurs d'un certain type pour
la durée d'une animation en spécifiant un ensemble de int
, float
ou une couleur ;
pour l'animation. Vous obtenez un ValueAnimator
en appelant l'une des
ses méthodes de fabrique: ofInt()
, ofFloat()
ou ofObject()
. Exemple :
Kotlin
ValueAnimator.ofFloat(0f, 100f).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f); animation.setDuration(1000); animation.start();
Dans ce code, ValueAnimator
commence à calculer les valeurs de la
, comprise entre 0 et 100, pour une durée de 1 000 ms, lorsque la méthode start()
est exécutée.
Vous pouvez également spécifier un type personnalisé à animer en procédant comme suit :
Kotlin
ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply { duration = 1000 start() }
Java
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue); animation.setDuration(1000); animation.start();
Dans ce code, ValueAnimator
commence à calculer les valeurs de l'animation, entre startPropertyValue
et endPropertyValue
, à l'aide de la logique fournie par MyTypeEvaluator
pendant une durée de 1 000 ms, lorsque la méthode start()
s'exécute.
Vous pouvez utiliser les valeurs de l'animation en ajoutant un AnimatorUpdateListener
à l'objet ValueAnimator
, comme indiqué dans le code suivant :
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); } });
Dans le onAnimationUpdate()
vous pouvez accéder à la valeur d'animation mise à jour et l'utiliser dans une propriété de
l'une de vos vues. Pour en savoir plus sur les écouteurs, consultez la section
Écouteurs d'animation.
Créer des animations à l'aide d'ObjectAnimator
ObjectAnimator
est une sous-classe de ValueAnimator
(décrite dans la section précédente) et combine le moteur de temporisation et le calcul de valeur de ValueAnimator
avec la possibilité d'animer une propriété nommée d'un objet cible. Cela facilite grandement l'animation de n'importe quel objet, car vous n'avez plus besoin d'implémenter ValueAnimator.AnimatorUpdateListener
, car la propriété animée est mise à jour automatiquement.
L'instanciation d'un ObjectAnimator
est semblable à celle d'un ValueAnimator
, mais vous devez également spécifier l'objet et le nom de la propriété de cet objet (sous forme de chaîne) ainsi que les valeurs à animer entre :
Kotlin
ObjectAnimator.ofFloat(textView, "translationX", 100f).apply { duration = 1000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f); animation.setDuration(1000); animation.start();
Pour que les propriétés de mise à jour ObjectAnimator
soient correctement appliquées, procédez comme suit :
- La propriété d'objet que vous animez doit comporter une fonction setter (en CamelCase) au format
set<PropertyName>()
. Étant donné queObjectAnimator
met automatiquement à jour la propriété pendant l'animation, il doit pouvoir y accéder avec cette méthode de setter. Par exemple, si le nom de la propriété estfoo
, vous devez disposer d'une méthodesetFoo()
. Si cette méthode setter n'existe pas, vous avez trois options: <ph type="x-smartling-placeholder">- </ph>
- Ajoutez la méthode "setter" à la classe si vous disposez des droits nécessaires.
- Utilisez une classe de wrapper que vous avez le droit de modifier et faites en sorte que ce wrapper reçoive la valeur avec une méthode de setter valide et la transfère à l'objet d'origine.
- Utilisez
ValueAnimator
à la place.
- Si vous ne spécifiez qu'une seule valeur pour le paramètre
values...
dans l'une des méthodes de fabriqueObjectAnimator
, elle est supposée être la valeur de fin de la de l'animation. La propriété d'objet que vous animez doit donc avoir une fonction getter. utilisée pour obtenir la valeur de départ de l'animation. La fonction getter doit se trouver dans au formatget<PropertyName>()
. Par exemple, si le nom de la propriété estfoo
, vous devez disposer d'une méthodegetFoo()
. - Les méthodes getter (si nécessaire) et setter de la propriété que vous animez doivent
opèrent sur le même type que les valeurs de début et de fin que vous spécifiez dans
ObjectAnimator
. Par exemple, vous devez disposer detargetObject.setPropName(float)
et detargetObject.getPropName()
si vous créez laObjectAnimator
suivante :ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- Selon la propriété ou l'objet que vous animez, vous devrez peut-être appeler la méthode
invalidate()
sur une vue pour forcer l'écran à se redessiner avec le les valeurs animées mises à jour. Pour ce faire, utilisezonAnimationUpdate()
. Par exemple, l'animation de la propriété couleur d'un objet Drawable ne provoque que des mises à jour de la à l'écran lorsque cet objet se redessine. Tous les setters de propriété sur View, tels quesetAlpha()
etsetTranslationX()
invalider la vue correctement. Vous n'avez donc pas besoin d'invalider la vue lorsque vous appelez ces avec de nouvelles valeurs. Pour en savoir plus sur les écouteurs, consultez la section sur les écouteurs d'animation.
Chorégraphiez plusieurs animations à l'aide d'AnimatorSet
Dans de nombreux cas, vous souhaitez lire une animation qui dépend du moment où une autre animation démarre ou
se termine. Le système Android vous permet de regrouper des animations dans une AnimatorSet
. Vous pouvez ainsi spécifier si les animations doivent démarrer simultanément, de manière séquentielle ou après un délai spécifié. Vous pouvez également imbriquer des objets AnimatorSet
les uns dans les autres.
L'extrait de code suivant lit l'élément Animator
suivant :
des objets de la manière suivante:
- Lire
bounceAnim
. - Lit
squashAnim1
,squashAnim2
,stretchAnim1
etstretchAnim2
en même temps. - Lit
bounceBackAnim
. - Lire
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();
Écouteurs d'animation
Vous pouvez écouter des événements importants pendant la durée d'une animation à l'aide des écouteurs décrits ci-dessous.
Animator.AnimatorListener
onAnimationStart()
- Appelé lorsque l'animation commence.onAnimationEnd()
– Appelé à la fin de l'animation.onAnimationRepeat()
: appelé lorsque l'animation se répète.onAnimationCancel()
: appelé lorsque l'animation est annulée. Une animation annulée appelle égalementonAnimationEnd()
, quelle que soit la façon dont elles ont été arrêtées.
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()
: appelé à chaque frame de l'animation. Écoutez cet événement pour utiliser les valeurs calculées générées parValueAnimator
lors d'une animation. Pour utiliser cette valeur, interrogez l'objetValueAnimator
. transmis à l'événement pour obtenir la valeur animée actuelle avec la méthodegetAnimatedValue()
. L'implémentation de cet écouteur est obligatoire si vous utilisezValueAnimator
.Selon la propriété ou l'objet que vous animez, vous devrez peut-être appeler
invalidate()
sur une vue pour forcer cette zone de la pour se redessiner avec les nouvelles valeurs animées. Par exemple, l'animation propriété color d'un objet drawable ne provoque des mises à jour de l'écran que lorsque cet objet se redessine automatiquement. Tous les setters de propriété sur View, tels quesetAlpha()
etsetTranslationX()
invalider la vue correctement, vous n'avez donc pas besoin d'invalider la vue lorsque vous appelez ces méthodes avec de nouvelles valeurs.
-
Vous pouvez étendre la classe AnimatorListenerAdapter
au lieu de
implémenter l'interface Animator.AnimatorListener
,
vous souhaitez implémenter toutes les méthodes de Animator.AnimatorListener
.
de commande. La classe AnimatorListenerAdapter
fournit une valeur
des méthodes que vous
pouvez choisir de remplacer.
Par exemple, l'extrait de code suivant crée un AnimatorListenerAdapter
pour onAnimationEnd()
uniquement
rappel:
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()); }
Animer les modifications de mise en page dans les objets ViewGroup
Le système d'animation des propriétés permet d'animer les modifications apportées aux objets ViewGroup. et permettent d'animer facilement les objets View eux-mêmes.
Vous pouvez animer les modifications de mise en page dans un ViewGroup avec la
LayoutTransition
. Les vues d'un ViewGroup
les animations apparaissent et disparaissent lorsque vous les ajoutez à
les supprimer d'un ViewGroup ou lorsque vous appelez la méthode
Méthode setVisibility()
avec
VISIBLE
, INVISIBLE
ou
GONE
Les vues restantes dans le ViewGroup
s'animent à leur nouvelle position lorsque vous ajoutez ou supprimez des vues. Vous pouvez définir
les animations suivantes dans un objet LayoutTransition
;
en appelant setAnimator()
et en transmettant un objet Animator
avec l'une des
Constantes LayoutTransition
suivantes:
APPEARING
: indicateur indiquant l'animation exécutée sur les éléments qui apparaissent dans le conteneur.CHANGE_APPEARING
: indicateur indiquant l'animation exécutée sur les éléments en raison de l'apparition d'un nouvel élément dans le conteneur.DISAPPEARING
: indicateur indiquant l'animation exécutée sur les éléments qui disparaissent du conteneur.CHANGE_DISAPPEARING
: indicateur indiquant l'animation exécutée sur les éléments qui changent en raison de la disparition d'un élément du conteneur.
Vous pouvez définir vos propres animations personnalisées pour ces quatre types d'événements afin de personnaliser l'apparence de vos transitions de mise en page ou simplement demander au système d'animation d'utiliser les animations par défaut.
Pour définir l'attribut android:animateLayoutchanges
sur true
pour le ViewGroup, procédez comme suit :
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />
Si vous définissez cet attribut sur "true", les vues ajoutées ou supprimées du ViewGroup, ainsi que les autres vues du ViewGroup, sont animées automatiquement.
Animer les changements d'état d'une vue à l'aide de StateListAnimator
La classe StateListAnimator
vous permet de définir des animateurs qui s'exécutent lorsque l'état d'une vue change. Cet objet se comporte comme un wrapper pour
Animator
, qui appelle cette animation chaque fois que la valeur
l'état de la vue (par exemple, "appui" ou "sélectionné").
Le StateListAnimator
peut être défini dans une ressource XML avec une racine
Élément <selector>
et éléments <item>
enfants spécifiés chacun
un état de vue différent défini par la classe StateListAnimator
. Chaque <item>
contient la définition d'un ensemble d'animation de propriété.
Par exemple, le fichier suivant crée un animateur de liste d'états qui modifie l'échelle X et Y de la vue lorsqu'il est enfoncé :
<?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>
Pour associer l'animateur de liste d'états à une vue, ajoutez le
android:stateListAnimator
comme suit:
<Button android:stateListAnimator="@xml/animate_scale" ... />
Les animations définies dans animate_scale.xml
sont maintenant utilisées lorsque l'objet
les changements d'état.
Pour attribuer un animateur de liste d'états à une vue dans votre code, utilisez la méthode AnimatorInflater.loadStateListAnimator()
, puis attribuez l'animateur à votre vue avec la méthode View.setStateListAnimator()
.
Au lieu d'animer les propriétés de la vue, vous pouvez lancer une animation drawable entre
les changements d'état à l'aide de AnimatedStateListDrawable
.
Certains des widgets
système dans
Android 5.0 utilise ces animations par défaut. L'exemple suivant montre comment
pour définir un AnimatedStateListDrawable
en tant que ressource 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>
Utiliser un TypeEvaluator
Si vous souhaitez animer un type inconnu du système Android, vous pouvez créer le vôtre
en implémentant l'interface TypeEvaluator
. Les types qui
sont connus par le système Android sont int
, float
ou une couleur, qui sont
compatible avec les types IntEvaluator
, FloatEvaluator
et ArgbEvaluator
évaluateurs.
Il n'y a qu'une seule méthode à implémenter dans TypeEvaluator
de l'interface, la méthode evaluate()
. Cela permet
l'animation que vous utilisez pour renvoyer une valeur appropriée pour votre propriété animée au niveau
point actuel de l'animation. La classe FloatEvaluator
illustre
procédez comme suit:
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); } }
Remarque : Lorsque ValueAnimator
(ou ObjectAnimator
) s'exécute, il calcule une fraction écoulée actuelle de l'animation (une valeur comprise entre 0 et 1), puis calcule une version interpolée de celle-ci en fonction de l'interpolater que vous utilisez. La fraction interpolée est ce que votre TypeEvaluator
reçoit via le paramètre fraction
. Vous devez donc
sans tenir compte de l'interpolateur lors du calcul des valeurs animées.
Utiliser des interpolateurs
Un interpolateur définit la façon dont les valeurs spécifiques d'une animation sont calculées en fonction du temps. Par exemple, vous pouvez spécifier que les animations doivent se dérouler de façon linéaire tout au long de l'animation, c'est-à-dire que l'animation se déplace uniformément tout au long de la vidéo, ou vous pouvez spécifier des animations à utiliser une durée non linéaire (par exemple, en utilisant l'accélération ou la décélération au début ou à la fin de la de l'animation.
Les interpolateurs du système d'animation reçoivent une fraction des animateurs qui représente le temps écoulé de l'animation. Les interpolateurs modifient cette fraction pour qu'elle coïncide avec le type de
l'animation qu'il vise à fournir. Le système Android fournit un ensemble d'interpolateurs courants dans android.view.animation package
. Si aucune de ces options ne répond à vos besoins, vous pouvez implémenter l'interface TimeInterpolator
et créer la vôtre.
À titre d'exemple, la comparaison ci-dessous montre comment l'interpolateur par défaut AccelerateDecelerateInterpolator
et le LinearInterpolator
calculent les fractions interpolées.
LinearInterpolator
n'a aucun effet sur la fraction écoulée. AccelerateDecelerateInterpolator
accélère dans l'animation et ralentit en dehors de celle-ci. Les méthodes suivantes définissent la logique de ces interpolateurs:
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; }
Le tableau suivant représente les valeurs approximatives calculées par ces interpolateurs pour une animation de 1 000 ms :
ms écoulés | Fraction écoulée/Fraction interpolée (linéaire) | Fraction interpolée (accélération/décélération) |
---|---|---|
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 |
Comme le montre le tableau, LinearInterpolator
modifie les valeurs
à la même vitesse, soit 0,2 par tranche de 200 ms. AccelerateDecelerateInterpolator
modifie les valeurs plus rapidement que LinearInterpolator
entre 200 ms et 600 ms, et plus lentement entre 600 ms et 1 000 ms.
Spécifier des images clés
Un objet Keyframe
se compose d'une paire temps/valeur qui vous permet de définir un état spécifique à un moment spécifique d'une animation. Chaque image clé peut aussi avoir sa propre
pour contrôler le comportement de l'animation dans l'intervalle entre
et celle de l'image clé.
Pour instancier un objet Keyframe
, vous devez utiliser l'une des méthodes de fabrique
méthodes, ofInt()
, ofFloat()
ou ofObject()
pour obtenir le type approprié de Keyframe
. Vous appelez ensuite la méthode de fabrique ofKeyframe()
pour obtenir un objet PropertyValuesHolder
. Une fois l'objet récupéré,
obtenir un animateur en transmettant l'objet PropertyValuesHolder
et
objet à animer. L'extrait de code suivant montre comment procéder:
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);
Animer des vues
Le système d'animation de propriété permet d'animer de manière simplifiée les objets View et offre quelques avantages par rapport au système d'animation de vue. Vue d'animation a transformé les objets View en modifiant la façon dont ils étaient dessinés. C'était gérées dans le conteneur de chaque vue, car la vue elle-même n'avait aucune propriété à manipuler. La vue était alors animée, mais l'objet View lui-même n'a pas été modifié. Cela a entraîné un comportement tel qu'un objet qui existait toujours à son emplacement d'origine, même s'il était dessiné à un autre emplacement à l'écran. Dans Android 3.0, de nouvelles propriétés et les méthodes getter et setter correspondantes ont été ajoutées pour éliminer cet inconvénient.
Le système d'animation des propriétés
pouvez animer les vues à l'écran en modifiant les propriétés réelles des objets View. Dans
De plus, les vues appellent automatiquement la méthode invalidate()
.
pour actualiser l'écran chaque fois que ses propriétés sont modifiées. Voici les nouvelles propriétés de la classe View
qui facilitent les animations de propriétés :
translationX
ettranslationY
: ces propriétés contrôlent l'emplacement de la vue en tant que delta par rapport à ses coordonnées gauche et supérieure, qui sont définies par son conteneur de mise en page.rotation
,rotationX
etrotationY
: ces propriétés contrôler la rotation en 2D (propriétérotation
) et en 3D autour du point pivot.scaleX
etscaleY
: ces propriétés contrôlent la mise à l'échelle 2D d'un Vue autour du point pivotpivotX
etpivotY
: ces propriétés contrôlent l'emplacement du point pivot autour duquel les transformations de rotation et de mise à l'échelle se produisent. Par défaut, le point pivot se trouve au centre de l'objet.x
ety
: il s'agit de propriétés utilitaires simples qui décrivent l'emplacement final de la vue dans son conteneur, en tant que somme des valeurs de gauche et de haut, ainsi que des valeurs translationX et translationY.alpha
: représente la transparence alpha de la vue. Cette valeur est définie sur 1 (opaque) par défaut, et une valeur de 0 représente une transparence totale (non visible).
Pour animer une propriété d'un objet View, comme sa couleur ou sa valeur de rotation, il vous suffit de créer un outil d'animation de propriété et spécifier la propriété View à et l'animation. Exemple :
Kotlin
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)
Java
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Pour en savoir plus sur la création d'animateurs, consultez les sections sur l'animation avec ValueAnimator et ObjectAnimator.
Créer une animation à l'aide de ViewPropertyAnimator
ViewPropertyAnimator
permet d'animer facilement plusieurs
les propriétés d'un View
en parallèle, à l'aide d'un seul Animator
sous-jacent
. Il se comporte comme un ObjectAnimator
, car il modifie les valeurs réelles des propriétés de la vue, mais il est plus efficace pour animer plusieurs propriétés à la fois. De plus, le code d'utilisation de ViewPropertyAnimator
est très
plus concis et
plus facile à lire. Les extraits de code suivants montrent les différences entre l'utilisation de plusieurs objets ObjectAnimator
, d'un seul ObjectAnimator
et de ViewPropertyAnimator
lors de l'animation simultanée des propriétés x
et y
d'une vue.
Plusieurs objets 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);
Pour en savoir plus sur ViewPropertyAnimator
, consultez les développeurs Android correspondants
blog
post.
Déclarer des animations en XML
Le système d'animation des propriétés vous permet de déclarer des animations de propriétés avec XML au lieu de faire de manière programmatique. En définissant vos animations en XML, vous pouvez facilement les réutiliser dans plusieurs activités et modifier plus facilement la séquence d'animation.
Pour distinguer les fichiers d'animation qui utilisent les nouvelles API d'animation de propriété de ceux qui utilisent l'ancien framework d'animation de vue, à partir d'Android 3.1, vous devez enregistrer les fichiers XML pour les animations de propriété dans le répertoire res/animator/
.
Les classes d'animation de propriété suivantes acceptent la déclaration XML avec la propriété les balises XML suivantes:
ValueAnimator
:<animator>
ObjectAnimator
:<objectAnimator>
AnimatorSet
:<set>
Pour trouver les attributs que vous pouvez utiliser dans votre déclaration XML, consultez la section Ressources d'animation. L'exemple suivant lit les deux ensembles d'animations d'objets de manière séquentielle, le premier ensemble imbriqué lisant deux animations d'objets ensemble:
<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>
Pour exécuter cette animation, vous devez gonfler les ressources XML dans le code en un objet AnimatorSet
, puis définir les objets cibles de toutes les animations avant de démarrer l'ensemble d'animation. Pour simplifier les choses, l'appel de setTarget()
spécifie un objet cible unique pour tous les enfants de AnimatorSet
. Pour ce faire, entrez le code suivant :
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();
Vous pouvez également déclarer un ValueAnimator
en XML, comme illustré dans l'exemple suivant :
<animator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:valueType="floatType" android:valueFrom="0f" android:valueTo="-100f" />
Pour utiliser l'ValueAnimator
précédent dans votre code, vous devez gonfler l'objet, ajouter un AnimatorUpdateListener
, obtenir la valeur d'animation mise à jour et l'utiliser dans une propriété de l'une de vos vues, comme indiqué dans le code suivant :
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();
Pour en savoir plus sur la syntaxe XML permettant de définir des animations de propriétés, consultez la section Ressources d'animation.
Effets potentiels sur les performances de l'interface utilisateur
Les animateurs qui mettent à jour l'interface utilisateur entraînent un rendu supplémentaire pour chaque image dans l'exécution de l'animation. C'est pourquoi l'utilisation d'animations gourmandes en ressources peut avoir un impact négatif sur les performances de votre application.
Le travail requis pour animer votre UI est ajouté à l'étape d'animation du pipeline de rendu. Vous pouvez savoir si vos animations ont un impact sur le les performances de votre application en activant le rendu GPU du profil, en surveillant l'étape de l'animation. Pour en savoir plus, consultez la section Présentation de Profile GPU Rendering.