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
animationSpecusingtween+ easing orspring. - Combine several to animate multiple properties together.
- Use
finishedListenerto 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
- Why Animations Matter
- animate*AsState Basics
- AnimatedVisibility and Transitions
- Gesture and Spring Animations