Bon nombre des API Animation acceptent des paramètres qui permettent de personnaliser leur comportement.
Personnaliser les animations avec le paramètre AnimationSpec
La plupart des API d'animation permettent aux développeurs de personnaliser les spécifications d'animation à l'aide d'un paramètre AnimationSpec
facultatif.
val alpha: Float by animateFloatAsState( targetValue = if (enabled) 1f else 0.5f, // Configure the animation duration and easing. animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing), label = "alpha" )
Il existe plusieurs types de AnimationSpec
, qui permettent de créer autant d'animations différentes.
Créer une animation basée sur la physique avec spring
spring
crée une animation basée sur des mécanismes physiques entre les valeurs de début et de fin. Deux paramètres sont acceptés : dampingRatio
et stiffness
.
dampingRatio
définit la force du rebond. La valeur par défaut est Spring.DampingRatioNoBouncy
.
Figure 1 : Définir différents ratios de freinage des ressorts
stiffness
définit la vitesse à laquelle le ressort doit se déplacer vers la valeur de fin. La valeur par défaut est Spring.StiffnessMedium
.
Figure 2. Définir une raideur de ressort différente
val value by animateFloatAsState( targetValue = 1f, animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ), label = "spring spec" )
spring
permet de gérer les interruptions plus en douceur par rapport aux types AnimationSpec
basés sur la durée, car il maintient la vitesse lorsque la valeur cible change entre les animations. De nombreuses API d'animation, dont animate*AsState
et updateTransition
, utilisent spring
comme AnimationSpec par défaut.
Par exemple, si nous appliquons une configuration spring
à l'animation suivante, qui est pilotée par le toucher de l'utilisateur, lorsque vous interrompez l'animation en cours, vous pouvez constater que l'utilisation de tween
ne répond pas aussi bien que celle de spring
.
Figure 3. Définir des spécifications tween
par rapport à spring
pour l'animation et l'interrompre
Animer entre les valeurs de début et de fin avec une courbe de lissage de vitesse avec tween
tween
crée une animation entre les valeurs de début et de fin durant la période durationMillis
spécifiée en suivant une courbe de lissage de vitesse. tween
est l'abréviation du mot "entre", car il se situe entre deux valeurs.
Vous pouvez également spécifier delayMillis
pour reporter le début de l'animation.
val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, delayMillis = 50, easing = LinearOutSlowInEasing ), label = "tween delay" )
Pour en savoir plus, consultez la section Easing.
Animer vers des valeurs spécifiques à des moments spécifiques avec keyframes
keyframes
crée une animation en fonction des valeurs d'instantané spécifiées à différents horodatages pendant la durée de l'animation. À un moment donné, la valeur d'animation est interpolée entre deux valeurs d'image clé. Vous pouvez spécifier la courbe d'interpolation de chacune de ces images clés en utilisant Easing.
De manière facultative, vous pouvez spécifier les valeurs à 0 ms et pour toute la durée. Dans le cas contraire, elles seront définies par défaut sur les valeurs de début et de fin de l'animation, respectivement.
val value by animateFloatAsState( targetValue = 1f, animationSpec = keyframes { durationMillis = 375 0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms 0.2f at 15 using FastOutLinearInEasing // for 15-75 ms 0.4f at 75 // ms 0.4f at 225 // ms }, label = "keyframe" )
Répéter une animation avec repeatable
repeatable
exécute plusieurs fois une animation basée sur la durée (par exemple, tween
ou keyframes
) jusqu'à atteindre le nombre d'itérations spécifié. Vous pouvez transmettre le paramètre repeatMode
pour indiquer si l'animation doit être répétée en commençant par le début (RepeatMode.Restart
) ou par la fin (RepeatMode.Reverse
).
val value by animateFloatAsState( targetValue = 1f, animationSpec = repeatable( iterations = 3, animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "repeatable spec" )
Répéter une animation indéfiniment avec infiniteRepeatable
infiniteRepeatable
est semblable à repeatable
, mais l'animation se répète indéfiniment.
val value by animateFloatAsState( targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "infinite repeatable" )
Dans les tests avec ComposeTestRule
, les animations qui utilisent infiniteRepeatable
ne sont pas exécutées. La valeur initiale de chaque valeur animée sera utilisée pour afficher le composant.
Ancrer immédiatement la valeur de fin avec snap
snap
est un AnimationSpec
spécial qui remplace immédiatement la valeur par la valeur de fin. Vous pouvez spécifier delayMillis
pour retarder le début de l'animation.
val value by animateFloatAsState( targetValue = 1f, animationSpec = snap(delayMillis = 50), label = "snap spec" )
Définir une fonction d'atténuation personnalisée
Les opérations AnimationSpec
basées sur la durée (telles que tween
ou keyframes
) utilisent Easing
pour ajuster une fraction d'une animation. Cela permet à la valeur d'animation d'accélérer et de ralentir plutôt que de se déplacer à une vitesse constante. La fraction est une valeur comprise entre 0 (début) et 1.0 (fin). Elle indique le point actuellement atteint dans l'animation.
En réalité, Easing est une fonction qui accepte une valeur de fraction comprise entre 0 et 1.0 et renvoie un float. La valeur renvoyée peut se trouver en dehors des limites pour représenter un dépassement vers le haut ou vers le bas. Vous pouvez créer un Easing personnalisé comme dans le code ci-dessous.
val CustomEasing = Easing { fraction -> fraction * fraction } @Composable fun EasingUsage() { val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, easing = CustomEasing ), label = "custom easing" ) // …… }
Compose intègre plusieurs fonctions Easing
qui couvrent la plupart des cas d'utilisation.
Pour déterminer quel lissage de vitesse utiliser selon votre scénario, consultez la section sur la vitesse dans Material Design.
FastOutSlowInEasing
LinearOutSlowInEasing
FastOutLinearEasing
LinearEasing
CubicBezierEasing
- Voir plus
Animer des types de données personnalisés en convertissant vers et depuis AnimationVector
La plupart des API d'animation Compose acceptent les types Float
, Color
et Dp
, ainsi que d'autres types de données de base en tant que valeurs d'animation par défaut, mais vous devez parfois animer d'autres types de données, y compris des types personnalisés. Pendant l'animation, les valeurs d'animation sont représentées par un AnimationVector
. Elles sont converties en AnimationVector
et inversement par un TwoWayConverter
associé afin que le système d'animation principal puisse les gérer de manière uniforme. Par exemple, Int
est représenté par un AnimationVector1D
contenant une seule valeur flottante.
Le TwoWayConverter
d'un Int
se présente comme suit :
val IntToVector: TwoWayConverter<Int, AnimationVector1D> = TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
Color
est essentiellement un ensemble de quatre valeurs (rouge, vert, bleu et alpha). Color
est donc converti en un AnimationVector4D
qui contient quatre floats. Ainsi, chaque type de données utilisé dans les animations est converti en AnimationVector1D
, AnimationVector2D
, AnimationVector3D
ou AnimationVector4D
en fonction de sa dimensionnalité. Cela permet d'animer indépendamment les différents composants de l'objet, chacun avec son propre suivi de la vitesse. Vous pouvez accéder aux convertisseurs intégrés des types de données de base à l'aide de convertisseurs tels que Color.VectorConverter
ou Dp.VectorConverter
.
Lorsque vous souhaitez proposer un nouveau type de données en tant que valeur d'animation, créez votre TwoWayConverter
et fournissez-le à l'API. Par exemple, vous pouvez utiliser animateValueAsState
pour animer votre type de données personnalisé comme suit :
data class MySize(val width: Dp, val height: Dp) @Composable fun MyAnimation(targetSize: MySize) { val animSize: MySize by animateValueAsState( targetSize, TwoWayConverter( convertToVector = { size: MySize -> // Extract a float value from each of the `Dp` fields. AnimationVector2D(size.width.value, size.height.value) }, convertFromVector = { vector: AnimationVector2D -> MySize(vector.v1.dp, vector.v2.dp) } ), label = "size" ) }
La liste suivante inclut quelques VectorConverter
intégrés:
Color.VectorConverter
Dp.VectorConverter
Offset.VectorConverter
Int.VectorConverter
Float.VectorConverter
IntSize.VectorConverter
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Animations basées sur la valeur
- Développement de code itératif {:#iterative-code-dev }
- Animations dans Compose