0Pricing
Android Academy · Leçon

Principes d’animate*AsState

Animez harmonieusement des valeurs individuelles.

Principes d’animate*AsState est une leçon Android Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Android Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Android Academy comprend 4 leçons au total.

Animer une valeur unique

La manière la plus simple d’animer dans Compose consiste à utiliser la famille animate*AsState. Vous lui fournissez une valeur cible et elle renvoie un State qui anime progressivement la valeur actuelle vers la valeur cible chaque fois que celle-ci change.

Il existe une variante pour chaque type courant : animateFloatAsState, animateDpAsState, animateColorAsState, animateOffsetAsState, et bien d’autres.

animateFloatAsState

animateFloatAsState anime un seul Float. Une utilisation courante est l’opacité (alpha). Lorsque visible change, l’alpha renvoyé glisse entre 0f et 1f.

Remarquez le mot-clé by : il vous permet de lire directement le State<Float> animé comme un simple Float.

@Composable
fun FadingLabel(visible: Boolean) {
    val alpha by animateFloatAsState(
        targetValue = if (visible) 1f else 0f,
        label = "alpha"
    )
    Text(
        "Hello",
        modifier = Modifier.graphicsLayer { this.alpha = alpha }
    )
}

animateDpAsState

Les tailles et les décalages de l’interface utilisent Dp : utilisez donc animateDpAsState pour animer la marge intérieure, la taille ou la position.

Ici, une boîte passe de 80dp à 160dp lorsqu’elle est activée ou désactivée. Comme nous transmettons le Dp animé à size(), la boîte se redimensionne progressivement.

@Composable
fun GrowingBox(big: Boolean) {
    val size by animateDpAsState(
        targetValue = if (big) 160.dp else 80.dp,
        label = "size"
    )
    Box(
        Modifier
            .size(size)
            .background(Color.Blue)
    )
}

animateColorAsState

Pour animer des couleurs, utilisez animateColorAsState. Cette fonction interpole dans l’espace colorimétrique afin que les transitions paraissent fluides et naturelles, plutôt que de produire des teintes intermédiaires étranges.

Ici, un point d’état passe progressivement du rouge au vert en fonction d’une valeur booléenne.

@Composable
fun StatusDot(online: Boolean) {
    val color by animateColorAsState(
        targetValue = if (online) Color(0xFF4CAF50) else Color(0xFFF44336),
        label = "status-color"
    )
    Box(
        Modifier
            .size(16.dp)
            .clip(CircleShape)
            .background(color)
    )
}

Personnaliser avec animationSpec

Par défaut, ces fonctions auxiliaires utilisent un ressort doux. Transmettez une animationSpec pour contrôler le minutage. Utilisez tween pour une durée fixe avec une courbe d’accélération.

Ce panneau glisse pendant 400 ms selon une courbe fluide qui accélère puis ralentit.

@Composable
fun SlidingPanel(open: Boolean) {
    val offset by animateDpAsState(
        targetValue = if (open) 0.dp else 250.dp,
        animationSpec = tween(
            durationMillis = 400,
            easing = FastOutSlowInEasing
        ),
        label = "offset"
    )
    Box(Modifier.offset(x = offset)) { /* content */ }
}

Courbes d’accélération

La courbe d’accélération détermine comment une animation accélère et ralentit. Compose en fournit plusieurs :

  • LinearEasing : vitesse constante (sensation mécanique).
  • FastOutSlowInEasing : valeur par défaut de Material ; démarrage rapide et fin douce.
  • LinearOutSlowInEasing : pour les éléments qui entrent à l’écran.
  • FastOutLinearInEasing : pour les éléments qui sortent de l’écran.

Choisir la bonne courbe donne au mouvement un aspect intentionnel plutôt que robotique.

val progress by animateFloatAsState(
    targetValue = if (done) 1f else 0f,
    animationSpec = tween(500, easing = LinearOutSlowInEasing),
    label = "progress"
)

Spécifications des ressorts

Au lieu d’une durée fixe, vous pouvez utiliser un ressort, qui produit une sensation physique et naturelle. Un ressort est défini par dampingRatio (son rebond) et stiffness (sa rapidité).

Les ressorts sont très utiles, car ils s’adaptent progressivement même lorsque la cible change au cours de l’animation.

val scale by animateFloatAsState(
    targetValue = if (active) 1.2f else 1f,
    animationSpec = spring(
        dampingRatio = Spring.DampingRatioMediumBouncy,
        stiffness = Spring.StiffnessLow
    ),
    label = "scale"
)

Réagir à la fin

Vous devez parfois effectuer une action lorsqu’une animation se termine, par exemple déclencher un rappel lorsque la valeur atteint sa cible. animate*AsState accepte précisément pour cela un finishedListener.

val alpha by animateFloatAsState(
    targetValue = if (gone) 0f else 1f,
    label = "alpha",
    finishedListener = { finalValue ->
        if (finalValue == 0f) onFullyHidden()
    }
)

Animer plusieurs propriétés

Vous pouvez combiner plusieurs appels à animate*AsState pour animer plusieurs propriétés à la fois. Chacun suit sa propre valeur et, ensemble, ils créent un effet plus riche.

Ici, une pastille change à la fois d’échelle et de couleur lorsqu’elle est sélectionnée.

@Composable
fun SelectableChip(selected: Boolean, text: String) {
    val scale by animateFloatAsState(if (selected) 1.1f else 1f, label = "s")
    val bg by animateColorAsState(
        if (selected) Color(0xFF3F51B5) else Color.LightGray,
        label = "bg"
    )
    Box(
        Modifier
            .graphicsLayer { scaleX = scale; scaleY = scale }
            .clip(RoundedCornerShape(16.dp))
            .background(bg)
            .padding(horizontal = 12.dp, vertical = 6.dp)
    ) { Text(text) }
}

Un ressort en Kotlin pur

Pour vous donner une intuition de ce que « fait » un ressort, voici une petite simulation en Kotlin pur. À chaque étape, elle rapproche une valeur de sa cible avec un certain amortissement, un peu comme le ressort de Compose converge vers votre valeur cible au fil des images.

fun main() {
    var value = 0f
    val target = 100f
    var velocity = 0f
    val stiffness = 0.1f
    val damping = 0.6f
    repeat(6) { step ->
        val force = (target - value) * stiffness
        velocity = (velocity + force) * damping
        value += velocity
        println("step $step -> ${"%.1f".format(value)}")
    }
}

Animer un entier et un décalage

La famille ne se limite pas aux nombres flottants et aux couleurs. Utilisez animateIntAsState pour les valeurs entières, comme la valeur cible d’un compteur de badge, et animateOffsetAsState ou animateIntOffsetAsState pour animer une position en deux dimensions en un seul appel.

Ici, une pastille glisse en diagonale grâce à l’animation d’un IntOffset.

@Composable
fun SlidingChip(moved: Boolean) {
    val pos by animateIntOffsetAsState(
        targetValue = if (moved) IntOffset(120, 60) else IntOffset.Zero,
        label = "pos"
    )
    Box(
        Modifier
            .offset { pos }
            .size(40.dp)
            .background(Color.Magenta)
    )
}

Vérification rapide

Vous souhaitez animer progressivement la largeur d’une boîte, mesurée en Dp, lorsqu’une valeur booléenne change. Quelle API convient le mieux ?

Récapitulatif&nbsp;: animate*AsState

La famille animate*AsState est votre choix privilégié pour animer une valeur unique :

  • Choisissez la variante correspondant au type : animateFloatAsState, animateDpAsState, animateColorAsState, etc.
  • Définissez un targetValue ; le résultat s’anime vers cette valeur à chaque changement.
  • Ajustez le mouvement avec animationSpec en utilisant tween et une courbe d’accélération, ou spring.
  • Combinez-en plusieurs pour animer plusieurs propriétés ensemble.
  • Utilisez finishedListener pour réagir à la fin d’une animation.

Ensuite : animer l’apparition et la disparition du contenu avec AnimatedVisibility et les transitions.

Questions Fréquemment Posées

La leçon « Principes d’animate*AsState » est-elle gratuite ?

Oui — le texte complet de « Principes d’animate*AsState » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Android Academy, passe à CoddyKit PRO. Le cours Android Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Principes d’animate*AsState » ?

Animez harmonieusement des valeurs individuelles. Tu pratiques Android Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Android Academy ?

Aucune expérience préalable n'est requise. Android Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Principes d’animate*AsState » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Android Academy ?

Oui. Chaque leçon Android Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Pourquoi les animations sont importantes
  2. Principes d’animate*AsState
  3. AnimatedVisibility et transitions
  4. Animations gestuelles et à ressort
← Retour à Android Academy