0Pricing
Android Academy · Lesson

AnimatedVisibility and Transitions

Animate showing and hiding content.

AnimatedVisibility and Transitions is a free Android Academy lesson on CoddyKit — lesson 3 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.

Animating Appearance

Showing and hiding content abruptly feels jarring. Compose's AnimatedVisibility animates a composable as it enters and exits the layout.

Wrap your content in it and control visibility with a boolean. When that boolean changes, Compose plays an enter or exit animation instead of an instant pop.

@Composable
fun Greeting(show: Boolean) {
    AnimatedVisibility(visible = show) {
        Text("Welcome aboard!")
    }
}

Enter and Exit Transitions

You can choose exactly how content enters and leaves with the enter and exit parameters. Common building blocks include fadeIn/fadeOut, slideIn/slideOut, and expandVertically/shrinkVertically.

Combine them with the + operator to run several at once.

@Composable
fun Toast(show: Boolean) {
    AnimatedVisibility(
        visible = show,
        enter = fadeIn() + slideInVertically { it },
        exit = fadeOut() + slideOutVertically { it }
    ) {
        Text("Item added to cart")
    }
}

Tuning the Transition Spec

Each enter/exit transition accepts an animationSpec, so you can control duration and easing just like with animate*AsState.

Here the content fades in over 300ms and out faster, over 150ms, a common pattern that makes dismissals feel snappy.

AnimatedVisibility(
    visible = show,
    enter = fadeIn(animationSpec = tween(300)),
    exit = fadeOut(animationSpec = tween(150))
) {
    Card { Text("Details") }
}

Expand and Shrink

For sections that reveal more content, expandVertically and shrinkVertically animate the height, pushing surrounding content smoothly out of the way.

This is perfect for collapsible panels, FAQ items, or "show more" sections.

@Composable
fun Details(expanded: Boolean) {
    AnimatedVisibility(
        visible = expanded,
        enter = expandVertically() + fadeIn(),
        exit = shrinkVertically() + fadeOut()
    ) {
        Text("Extra details revealed when expanded.")
    }
}

updateTransition: One State, Many Values

When several properties should change together based on one state, updateTransition coordinates them. It creates a Transition object whose children all animate in sync.

Define the state, then use animateColor, animateDp, etc., for each property as a function of that state.

enum class BoxState { Collapsed, Expanded }

@Composable
fun MorphingBox(state: BoxState) {
    val transition = updateTransition(state, label = "box")
    val size by transition.animateDp(label = "size") {
        if (it == BoxState.Expanded) 200.dp else 100.dp
    }
    val color by transition.animateColor(label = "color") {
        if (it == BoxState.Expanded) Color.Magenta else Color.Cyan
    }
    Box(Modifier.size(size).background(color))
}

Per-Property Timing in a Transition

A big advantage of updateTransition is per-property timing. Each animate* child can supply its own transitionSpec, so color and size can move at different speeds while staying coordinated by the same state.

val size by transition.animateDp(
    transitionSpec = { tween(durationMillis = 300) },
    label = "size"
) { if (it == BoxState.Expanded) 200.dp else 100.dp }

val corner by transition.animateDp(
    transitionSpec = { tween(durationMillis = 600) },
    label = "corner"
) { if (it == BoxState.Expanded) 0.dp else 24.dp }

AnimatedContent: Swapping Content

When the content itself changes, not just its visibility, use AnimatedContent. It animates between the old and new content, cross-fading by default.

It's ideal for things like a counter, a step indicator, or switching between loading and loaded states.

@Composable
fun Counter(count: Int) {
    AnimatedContent(
        targetState = count,
        label = "counter"
    ) { value ->
        Text("$value", style = MaterialTheme.typography.headlineLarge)
    }
}

Custom AnimatedContent Transitions

Customize how AnimatedContent swaps with transitionSpec. A classic for a counter is sliding the new value up while the old slides away, paired with a fade.

The using keyword attaches a SizeTransform so the container also resizes smoothly.

AnimatedContent(
    targetState = count,
    transitionSpec = {
        (slideInVertically { it } + fadeIn()) togetherWith
            (slideOutVertically { -it } + fadeOut())
    },
    label = "counter"
) { value -> Text("$value") }

Animating List Items

Inside a LazyColumn, items that are added, removed, or moved can animate into place with Modifier.animateItem() on each item's content.

This gives smooth reordering and insertion without any manual bookkeeping.

LazyColumn {
    items(tasks, key = { it.id }) { task ->
        Text(
            task.title,
            modifier = Modifier.animateItem()
        )
    }
}

Crossfade for Whole Screens

Crossfade is a simple, focused helper that fades between two states, great for switching whole screens or major UI states.

Pass the current state and a content lambda; when the state changes, Crossfade fades the old out and the new in.

@Composable
fun ScreenHost(screen: Screen) {
    Crossfade(targetState = screen, label = "screen") { current ->
        when (current) {
            Screen.Home -> HomeScreen()
            Screen.Profile -> ProfileScreen()
        }
    }
}

Coordinating Enter Children

Inside an AnimatedVisibility block you get an AnimatedVisibilityScope, which exposes Modifier.animateEnterExit(). This lets individual children animate with their own enter/exit on top of the parent's transition.

For example, a panel can slide in while its title fades in slightly later for a layered effect.

AnimatedVisibility(visible = show, enter = slideInVertically()) {
    Column {
        Text(
            "Title",
            modifier = Modifier.animateEnterExit(
                enter = fadeIn(tween(delayMillis = 100))
            )
        )
        Text("Body")
    }
}

Quick Check

You want to animate the swap from a number 3 to a number 4, fading and sliding the new value in. Which API is the best fit?

Recap: Visibility & Transitions

You can now animate content appearing, disappearing, and changing:

  • AnimatedVisibility animates enter/exit with fadeIn/Out, slideIn/Out, expand/shrink, combinable with +.
  • updateTransition coordinates many values from one state, each with its own spec.
  • AnimatedContent animates swaps between different content; Crossfade is the simple fade variant.
  • Modifier.animateItem() animates list insertions and reordering.

Next: gestures and physics-based spring animations for natural, interactive motion.

Frequently asked questions

Is the “AnimatedVisibility and Transitions” lesson free?

Yes — the full text of “AnimatedVisibility and Transitions” 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 “AnimatedVisibility and Transitions”?

Animate showing and hiding content. 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 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “AnimatedVisibility and Transitions” 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