Did you know that even small animations can increase user engagement in Android apps by up to 30%? I have been building Android interfaces for quite a while, and I have learned that animations are important. Jetpack Compose has completely changed how we design UIs because it is declarative and reactive. Now, creating smooth animations is easier than ever. One API that I find particularly useful is AnimatedVisibility
. It gives you control over whether composables are visible with animated transitions. This is very useful if you want to create user experiences that feel polished, and it saves you from the complicated old Android view system. Let us explore how to use AnimatedVisibility jetpack compose
to create amazing effects.
Understanding AnimatedVisibility Jetpack Compose
AnimatedVisibility
is a composable function that animates the appearance and disappearance of its content. I think it is essential for designing UI transitions that improve how users perceive the app by giving them visual cues and making the interface feel responsive. With AnimatedVisibility jetpack compose
, implementing effects like fade in, fade out, slide in and slide out is surprisingly simple and requires minimal code. I have tried so many options, and this one is a winner.
The basic syntax looks like this:
@Composablefun AnimatedVisibilityExample(isVisible: Boolean) { AnimatedVisibility( visible = isVisible, enter = fadeIn(animationSpec = tween(durationMillis = 500)), exit = fadeOut(animationSpec = tween(durationMillis = 500)) ) { // Content to be animated Text("Hello, Compose!") }}
In this example, the Text
composable will fade in when isVisible
is true
and fade out when isVisible
is false
. The tween
animation spec defines how long the animation lasts, which controls its speed.
Setting Up Your Project for AnimatedVisibility
Before you start using AnimatedVisibility jetpack compose
, make sure you have the right dependencies in your build.gradle.kts
file. This is important:
dependencies { implementation("androidx.compose.ui:ui") implementation("androidx.compose.animation:animation") implementation("androidx.compose.material:material") implementation("androidx.compose.ui:ui-tooling-preview") debugImplementation("androidx.compose.ui:ui-tooling")}
After you add these dependencies, sync your project so that all the libraries download correctly and link to your project. If you skip this step, you might run into problems later.
Basic Fade In/Out Animation with AnimatedVisibility
Let us begin with a basic fade in and fade out animation using AnimatedVisibility
. This is a common use. We will create a composable that toggles the visibility of a text element when you click a button.
@Composablefun FadeInOutExample() { var isVisible by remember { mutableStateOf(true) } Column { Button(onClick = { isVisible = !isVisible }) { Text("Toggle Visibility") } AnimatedVisibility( visible = isVisible, enter = fadeIn(animationSpec = tween(durationMillis = 500)), exit = fadeOut(animationSpec = tween(durationMillis = 500)) ) { Text("Now you see me, now you do not!") } }}
In this snippet:
We use
remember
andmutableStateOf
to manage the visibility state, so it is remembered across recompositions.A
Button
toggles theisVisible
state when clicked, switching between visible and invisible.The
AnimatedVisibility
composable animates the visibility of theText
based on theisVisible
state, watching for changes and triggering the animation.fadeIn
andfadeOut
are the enter and exit transitions, which control how the content appears and disappears.animationSpec = tween(durationMillis = 500)
sets the animation to last 500ms.
This is a basic example of how to use AnimatedVisibility jetpack compose
to create a fade in and fade out animation. The visible
parameter is important because it determines if the content is currently visible and animated.
Customizing Transitions with AnimatedVisibility
What makes AnimatedVisibility
great is that you can customize the enter and exit transitions. Compose has several transition options, and you can even create your own custom animations. I have found this to be incredibly valuable when I am creating unique user experiences.
Slide In/Out Transitions
To create a slide in and slide out animation, you can use the slideInVertically
and slideOutVertically
(or the horizontal versions) transitions. This will feel different from fading when using AnimatedVisibility jetpack compose
.
@Composablefun SlideInOutExample() { var isVisible by remember { mutableStateOf(true) } Column { Button(onClick = { isVisible = !isVisible }) { Text("Toggle Visibility") } AnimatedVisibility( visible = isVisible, enter = slideInVertically(animationSpec = tween(durationMillis = 500), initialOffsetY = { -it }), exit = slideOutVertically(animationSpec = tween(durationMillis = 500), targetOffsetY = { -it }) ) { Text("Sliding in and out!") } }}
Here, initialOffsetY = { -it }
means that the content will slide in from above the screen, and targetOffsetY = { -it }
means that it will slide out in the same direction. The it
parameter is the height of the content, making the slide proportional.
Combining Transitions for richer animations
You can combine transitions to create more complex effects with AnimatedVisibility
. For example, you can combine a fade in with a slide in for an animation that is richer and more engaging.
@Composablefun CombinedTransitionExample() { var isVisible by remember { mutableStateOf(true) } Column { Button(onClick = { isVisible = !isVisible }) { Text("Toggle Visibility") } AnimatedVisibility( visible = isVisible, enter = fadeIn(animationSpec = tween(durationMillis = 500)) + slideInVertically(animationSpec = tween(durationMillis = 500), initialOffsetY = { -it }), exit = fadeOut(animationSpec = tween(durationMillis = 500)) + slideOutVertically(animationSpec = tween(durationMillis = 500), targetOffsetY = { -it }) ) { Text("Fading and sliding!") } }}
In this case, the content will fade in and slide in from above at the same time, which creates a visually appealing effect.
Using Different Animation Specs
The animationSpec
parameter lets you customize the animation timing and behavior. Compose has several built in animation specs, including:
tween
: Creates a basic animation with a specific duration.spring
: Creates a spring based animation that acts like a physical spring, so it has a bouncy effect.keyframes
: Lets you define a sequence of keyframes for the animation, which gives you precise control over how the animation progresses.
For example, to use a spring animation:
enter = fadeIn(animationSpec = spring(dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessLow))
This will give you a fade in animation that is bouncy. The damping ratio and stiffness control how bouncy the animation is. Try different values to fine tune the effect.
Animating Multiple Properties
Sometimes, you might want to animate multiple composable properties at the same time. While AnimatedVisibility
mainly handles visibility, you can use it with other animation APIs like animateAsState
to animate properties such as size, color and position. This makes the effects more intricate and visually appealing.
For example, let us animate the size of a box along with its visibility:
@Composablefun AnimatedSizeAndVisibility() { var isVisible by remember { mutableStateOf(true) } val size by animateDpAsState( targetValue = if (isVisible) 100.dp else 0.dp, animationSpec = tween(durationMillis = 500)) Column { Button(onClick = { isVisible = !isVisible }) { Text("Toggle Visibility") } AnimatedVisibility( visible = isVisible ) { Box( modifier = Modifier .size(size) .background(Color.Red) ) } }}
In this example, the size
of the Box
is animated using animateDpAsState
. When isVisible
is true
, the size animates to 100dp; otherwise, it animates to 0dp. The AnimatedVisibility
controls whether the Box
is visible, so it appears and disappears smoothly.
Conditional Transitions
You can also create transitions that depend on different states. For example, you might want a different animation when a composable is added to the screen versus when it is removed. This gives you animations with more nuance and context using AnimatedVisibility jetpack compose
.
@Composablefun ConditionalTransitionExample() { var isVisible by remember { mutableStateOf(false) } var isEntering by remember { mutableStateOf(false) } Column { Button(onClick = { isVisible = !isVisible isEntering = isVisible // Update entering state }) { Text("Toggle Visibility") } AnimatedVisibility( visible = isVisible, enter = if (isEntering) fadeIn(animationSpec = tween(durationMillis = 500)) else slideInVertically(animationSpec = tween(durationMillis = 500)), exit = fadeOut(animationSpec = tween(durationMillis = 500)) ) { Text("Conditional Transition") } }}
In this snippet, the enter
transition is chosen based on the isEntering
state. When the composable is first shown (isEntering
is true
), it fades in. Otherwise, it slides in vertically, so the animation depends on the context.
Best Practices
Here are some best practices to remember when using AnimatedVisibility jetpack compose
:
Keep animations short and sweet: Animations that are too long or complex can be distracting and hurt the user experience. Aim for animations that are subtle and give clear visual feedback.
Use appropriate easing functions: Easing functions control how the animation changes over time. Choose easing functions that feel natural and match your app’s style.
Consider performance: Animations can use a lot of resources, especially on older devices. Optimize your animations to reduce lag and make sure they perform smoothly.
Test on different devices: Animations can look and act differently on different devices because the screens have different sizes, resolutions and processing power.
Advanced Techniques
For more advanced use cases, you can try creating custom transitions using the Transition
API. This API gives you more control over the animation and lets you animate multiple properties at the same time with complex timing and dependencies.
Another technique is to use the AnimatedContent
composable, which lets you animate between different content states. This is helpful when you want to replace one composable with another and have a smooth transition.
Accessibility Considerations
When you add animations to your app, think about accessibility. Users who are sensitive to motion might find animations distracting or even nauseating. Give them the option to disable animations or reduce how intense they are. Respect the animation preferences in the user’s system settings.
Also, make sure that animations do not show important information that users with disabilities might miss. Always have other ways to access the same information. For example, if an animation shows an error, also display the error as text.
Troubleshooting Common Issues
Here are some common issues that you might have when using AnimatedVisibility jetpack compose
and how to fix them:
Animation not playing: Double check that the
visible
parameter is being updated correctly and that the animation spec is set up correctly. Also, make sure that the composable is being recomposed when thevisible
state changes.Laggy animation: Make the animation shorter, simplify it or optimize the composable that is being animated. Also, check for recompositions that are not needed because they can interfere with the animation.
Unexpected behavior: Check the code for logical errors or assumptions that are incorrect. Try making the animation simpler to find the problem.
Real World Examples
To show how useful and adaptable AnimatedVisibility
is, let us look at some real world examples:
Showing and hiding a loading indicator: Use
AnimatedVisibility
to smoothly fade in a loading indicator while data is being fetched and fade it out when the data is ready.Displaying and hiding error messages: Animate how error messages appear to draw the user’s attention to them without being jarring.
Toggling whether a password field is visible: Use a slide in and slide out animation to reveal or hide a password field when the user taps a “show password” button.
Animating list item insertions and removals: Use
AnimatedVisibility
withLazyColumn
to animate list items when they are inserted and removed.
These are only some examples of how AnimatedVisibility jetpack compose
can improve the user experience. There are many possibilities!
Conclusion
AnimatedVisibility
in Kotlin Jetpack Compose is a great tool for creating user interfaces that are engaging and polished. If you understand the basics of fade in and fade out animations, can customize transitions and can combine animations with other Compose APIs, you can create visual effects that are truly impressive. Remember to think about accessibility and performance, and do not be afraid to try different animation specs and techniques. It is worth it to master AnimatedVisibility jetpack compose
.
References
Animation modifiers and composables

Comments