โ† Back to list

๐ŸŽฌ Seamless Entry and Exit Animations with AnimatedVisibility in Jetpack Compose

Learn how to animate your composables as they appear and disappear on screen using AnimatedVisibility, and create delightful, smooth UIโ€ฆ

Nishanth Selvaraju ยท 2025-11-13 02:01 ยท 1 claps ยท 3.2 min read paywalled
#android-animations #animatedvisibility #jetpack-compose
Open on Medium โ†—
Wiki topics: ๐Ÿ“ฑ ยท Mobile Development ๐ŸŽฌ ยท Film & Television

๐ŸŽฌ Seamless Entry and Exit Animations with AnimatedVisibility in Jetpack Compose

Learn how to animate your composables as they appear and disappear on screen using AnimatedVisibility, and create delightful, smooth UI transitions effortlessly.

๐Ÿš€ Intro: Visibility That Feels Alive

Imagine this: You toggle a button, and instead of a card suddenly popping in, it slides up gracefully. Or when dismissed, it fades away softly โ€” natural, fluid, and meaningful.

Thatโ€™s where AnimatedVisibility shines โ€” itโ€™s the Compose-native way to animate enter and exit transitions of composables based on state.

And unlike older approaches (using View animations or TransitionManager), this one is:

  • Declarative ๐Ÿงฉ
  • Lightweight โšก
  • Fully tied to Compose state management ๐Ÿ’ช

Today, weโ€™ll build a real example โ€” a โ€œShow More Detailsโ€ card that expands, fades, and shrinks with smooth motion.

๐Ÿง  Concept Overview: How AnimatedVisibility Works

The API is simple yet powerful:

AnimatedVisibility(visible = isVisible) {
    // Your composable content
}

When isVisible changes:

  • Compose automatically triggers the enter and exit animations.
  • You can customize those transitions with slide, expand, fade, or scale effects.

Letโ€™s see it in action ๐Ÿ‘‡

โš™๏ธ Implementation: Building the Interactive Animated Card

๐Ÿ”น Step 1: Basic Visibility Toggle

@Composable
fun AnimatedVisibilityDemo() {
    var isVisible by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(24.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Button(onClick = { isVisible = !isVisible }) {
            Text(if (isVisible) "Hide Details" else "Show Details")
        }

        Spacer(modifier = Modifier.height(20.dp))

        AnimatedVisibility(visible = isVisible) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(180.dp)
                    .clip(RoundedCornerShape(16.dp))
                    .background(Color(0xFF7E57C2)),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    "Compose makes animation easy!",
                    color = Color.White,
                    style = MaterialTheme.typography.titleMedium
                )
            }
        }
    }
}

โœจ Tap the button โ€” the card appears and disappears with default fade + expand animation.

๐Ÿ”น Step 2: Custom Enter and Exit Animations

Default is nice, but letโ€™s spice it up!

AnimatedVisibility(
    visible = isVisible,
    enter = fadeIn(animationSpec = tween(500)) +
            slideInVertically(initialOffsetY = { it }),
    exit = fadeOut(animationSpec = tween(400)) +
           slideOutVertically(targetOffsetY = { it / 2 })
) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(180.dp)
            .clip(RoundedCornerShape(16.dp))
            .background(Color(0xFF26C6DA)),
        contentAlignment = Alignment.Center
    ) {
        Text(
            "Custom enter/exit animations!",
            color = Color.White,
            style = MaterialTheme.typography.titleMedium
        )
    }
}

๐ŸŒ€ Now the card:

  • Slides in from below
  • Fades out partially upward when hidden

This combo feels natural and gives a smooth contextual reveal.

๐Ÿ”น Step 3: Combining Multiple Animated Elements

We can also animate multiple UI parts independently

@Composable
fun MultiElementAnimation() {
    var expanded by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(24.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Button(onClick = { expanded = !expanded }) {
            Text(if (expanded) "Collapse" else "Expand")
        }

        AnimatedVisibility(
            visible = expanded,
            enter = expandVertically() + fadeIn(),
            exit = shrinkVertically() + fadeOut()
        ) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .background(Color(0xFF42A5F5))
                    .padding(16.dp)
                    .clip(RoundedCornerShape(12.dp))
            ) {
                Text("User Profile", color = Color.White, fontSize = 18.sp)
                Spacer(Modifier.height(8.dp))
                Text("Name: Nishanth", color = Color.White)
                Text("Level: Advanced", color = Color.White)
                Text("Status: Online", color = Color.White)
            }
        }
    }
}

๐Ÿ’ก The column expands and collapses gracefully. No jarring pops โ€” just fluid motion.

๐Ÿงฉ Step 4: Animating Child Composables Inside

Want even more control? Each element inside AnimatedVisibility can have its own animation using animateEnterExit.

AnimatedVisibility(
    visible = expanded,
    enter = fadeIn(),
    exit = fadeOut()
) {
    Row(
        verticalAlignment = Alignment.CenterVertically
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = null,
            modifier = Modifier
                .animateEnterExit(
                    enter = slideInHorizontally(initialOffsetX = { -40 }),
                    exit = slideOutHorizontally(targetOffsetX = { 40 })
                )
                .padding(8.dp)
        )
        Text("Liked!", color = Color.White)
    }
}

๐ŸŽฏ Each child reacts differently โ€” giving your animation storytelling depth.

๐Ÿง  Pro Tip: Performance & Best Practices

โœ… Use AnimatedVisibility for state-driven UI, not frequent recompositions โœ… Keep animations short (300โ€“600ms) for UX comfort โœ… Use AnimatedContent for content replacement (next-level topic soon!) โœ… Remember: animations recompose efficiently, so no performance worry

๐Ÿงช Interactive Challenge

Try this yourself:

  1. Add expandHorizontally() + fadeIn() together
  2. Add an AnimatedVisibility around a LazyColumn
  3. Chain LaunchedEffect to start animation after 2 seconds
  4. Play with different animationSpec types (spring, tween, keyframes)

๐Ÿ’ก Every experiment shows how Compose builds motion declaratively.

๐Ÿงฉ Takeaway

AnimatedVisibility transforms how you handle dynamic layouts โ€” turning conditional rendering into beautiful motion.

โ€œVisibility is not just a state โ€” itโ€™s an experience.โ€

Mastering it gives you the confidence to craft UIs that breathe with state changes.

Before you leave โ€” -

  • ๐Ÿ’ฌ Iโ€™d love to hear from you! What topics would you like me to write about next? Letโ€™s learn and grow together! ๐ŸŒฑ
  • Follow me for more update on Andorid/kotlin and latest Tech
  • Give me a ๐Ÿ‘ Clap to put it one step up for others readers
  • Connect Me on on LinkedIn!

Thanks for the read!.

[embed]Nishanth Selvaraju - Medium Read writing from Nishanth Selvaraju on Medium. Android iOS Cross-Platform AI DevOps | 10+ Years in Mobilemedium.com


๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
post_id
dbb38dce4d0c
slug
seamless-entry-and-exit-animations-with-animatedvisibility-in-jetpack-compose-dbb38dce4d0c
url
https://medium.com/@snishanthdeveloper/seamless-entry-and-exit-animations-with-animatedvisibility-in-jetpack-compose-dbb38dce4d0c
canonical_url
https://medium.com/@snishanthdeveloper/seamless-entry-and-exit-animations-with-animatedvisibility-in-jetpack-compose-dbb38dce4d0c
author_url
https://medium.com/@snishanthdeveloper
status
ok
fetched_at
2026-09-17 10:54:01