← All courses

Animations

🗓 May 31, 2026 ⏱ 2 min read

Animation is built in

Compose makes animation remarkably easy because it already knows when your state changes. Most of the time you just say “animate this value” and Compose handles the frames.

animate*AsState — the simplest animation

@Composable
fun LikeButton(liked: Boolean) {
    val color by animateColorAsState(
        targetValue = if (liked) Color.Red else Color.Gray,
        label = "color"
    )
    val size by animateDpAsState(if (liked) 32.dp else 24.dp, label = "size")

    Icon(Icons.Default.Favorite, null, tint = color, modifier = Modifier.size(size))
}

Change liked and the color and size glide smoothly to their new values — no manual animation code.

Animating visibility

AnimatedVisibility(visible = expanded) {
    Text("Now you see me", Modifier.padding(8.dp))
}

AnimatedVisibility(
    visible = show,
    enter = slideInVertically() + fadeIn(),
    exit = slideOutVertically() + fadeOut()
) { DetailPanel() }

animateContentSize — smooth resize

Column(
    modifier = Modifier
        .animateContentSize()      // animate when content grows/shrinks
        .clickable { expanded = !expanded }
) {
    Text("Tap to expand")
    if (expanded) Text("Hidden details revealed here…")
}

Explicit animations with transitions

For coordinated, multi-property animations use updateTransition; for gesture-driven or looping animations use Animatable and rememberInfiniteTransition. Reach for these only when the simple APIs aren’t enough.

val alpha by rememberInfiniteTransition(label = "pulse").animateFloat(
    initialValue = 0.3f, targetValue = 1f,
    animationSpec = infiniteRepeatable(tween(800), RepeatMode.Reverse),
    label = "alpha"
)

Common mistakes

  • Animating everything — subtle motion feels premium; excessive motion feels noisy.
  • Reaching for low-level APIs when animate*AsState would do.
  • Forgetting that animations restart if the composable leaves and re-enters the tree.
Summary: Use animate*AsState for value changes, AnimatedVisibility for appear/disappear, and animateContentSize for resizing. Drop to transitions/Animatable only for complex motion.