0Pricing
Android Academy · Lesson

animate*AsState Basics

Smoothly animate single values.

animate*AsState Basics is a free Android Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Animate a Single Value

The simplest way to animate in Compose is the animate*AsState family. You give it a target value, and it returns a State that smoothly animates from the current value to the target whenever the target changes.

There's a variant for each common type: animateFloatAsState, animateDpAsState, animateColorAsState, animateOffsetAsState, and more.

animateFloatAsState

animateFloatAsState animates a single Float. A common use is opacity (alpha). When visible flips, the returned alpha glides between 0f and 1f.

Note the by keyword: it lets you read the animated State<Float> directly as a plain 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

UI sizes and offsets use Dp, so reach for animateDpAsState to animate padding, size, or position.

Here a box grows from 80dp to 160dp when toggled. Because we feed the animated Dp into size(), the box smoothly resizes.

@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

To animate colors, use animateColorAsState. It interpolates across the color space so transitions look smooth and natural rather than flickering through odd in-between hues.

Here a status dot animates between red and green based on a boolean.

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

Customizing with animationSpec

By default these helpers use a gentle spring. Pass an animationSpec to control timing. Use tween for a fixed duration with an easing curve.

This panel slides over 400ms with a smooth accelerate-then-decelerate curve.

@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 */ }
}

Easing Curves

Easing shapes how an animation accelerates and decelerates. Compose ships several:

  • LinearEasing - constant speed (mechanical feel).
  • FastOutSlowInEasing - the Material default; quick start, soft finish.
  • LinearOutSlowInEasing - for elements entering the screen.
  • FastOutLinearInEasing - for elements exiting.

Choosing the right easing makes motion feel intentional rather than robotic.

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

Spring Specs

Instead of a fixed duration you can use a spring, which feels physical and natural. A spring is defined by dampingRatio (how bouncy) and stiffness (how fast).

Springs are great because they adapt smoothly even when the target changes mid-animation.

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

Reacting to Finish

Sometimes you need to do something when an animation completes, like firing a callback once a value reaches its target. animate*AsState accepts a finishedListener for exactly this.

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

Animate Multiple Properties

You can combine several animate*AsState calls to animate more than one property at once. Each tracks its own value, and together they create a richer effect.

Here a chip both scales and changes color when selected.

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

A Spring in Pure Kotlin

To build intuition for what a spring "does", here's a tiny pure-Kotlin simulation. It nudges a value toward a target each step with some damping, much like Compose's spring resolves toward your target value over many frames.

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

Animating Int and Offset

The family extends beyond floats and colors. Use animateIntAsState for whole-number values like a badge count target, and animateOffsetAsState or animateIntOffsetAsState to animate 2D position in one call.

Here a chip slides diagonally by animating an 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)
    )
}

Quick Check

You want to smoothly animate a box's width, measured in Dp, when a boolean changes. Which API fits best?

Recap: animate*AsState

The animate*AsState family is your go-to for animating a single value:

  • Pick the typed variant: animateFloatAsState, animateDpAsState, animateColorAsState, etc.
  • Set a targetValue; the result animates toward it on every change.
  • Tune motion with animationSpec using tween + easing or spring.
  • Combine several to animate multiple properties together.
  • Use finishedListener to react when an animation completes.

Next: animating content appearing and disappearing with AnimatedVisibility and transitions.

Frequently asked questions

Is the “animate*AsState Basics” lesson free?

Yes — the full text of “animate*AsState Basics” is free to read here on the web, and the Android Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.

What will I learn in “animate*AsState Basics”?

Smoothly animate single values. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “animate*AsState Basics” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Why Animations Matter
  2. animate*AsState Basics
  3. AnimatedVisibility and Transitions
  4. Gesture and Spring Animations
← Back to Android Academy