Animating Visibility Changes in Jetpack Compose

Understanding and Implementing AnimatedVisibility()

Michihiro Iwasaki
4 min readJan 18, 2024

In Jetpack Compose, setting animations based on different scenarios is a straightforward process. This article will specifically explore how to animate the transitions between visible and invisible states of UI elements. By mastering AnimatedVisibility(), you can enhance the dynamic interactivity of your Compose applications.

☛ Understanding the Necessity of Animation

Before we delve into implementing animations, it’s crucial to understand why and when they should be used.

Animations consume device resources to varying degrees. Therefore, using animations unnecessarily isn’t advisable, as it could lead to resource wastage. However, when applied appropriately, animations can significantly enhance user experience and the overall quality of an app. Essentially, the key lies in knowing when and why to employ animations.

Consider this scenario: In an app for managing to-do lists, users can add and delete list items. These items need to switch between visible and invisible states. Imagine if an item suddenly disappears upon deletion. How would users react? Such abrupt changes can be disorienting and lead to confusion about which item was removed.

An image that a list item suddenly disappears.

To address this issue, animating the transition of list items’ visibility can be highly effective. By adding animations, the disappearance of a list item is more gradual, allowing users to easily recognize which item was deleted.

An image that a list item disappears with transitions

In this article, we’ll explore simple examples of animating the transition between visible and invisible states using AnimatedVisibility(). Please note that this tutorial focuses solely on the animation aspect and does not cover data persistence or deletion on servers or devices. However, keep in mind that handling data is a critical aspect of developing production applications.

Next, we’ll dive into implementing straightforward animations with AnimatedVisibility().

☛ Adding Simple Animations

Jetpack Compose natively supports a variety of animations, so you generally don’t need to add extra libraries in the gradle.kts file if you started your project with the 'Empty Activity' template. This convenience is a significant advantage when incorporating animations into your app.

Let’s first examine a scenario without animations. In the following example, a visible Boolean value toggles visibility upon button press, controlling the visibility of an element. While this code effectively switches between visible and invisible states, it lacks animation:

@Composable
fun NoAnimation(modifier: Modifier = Modifier) {

// visible state
var visible by remember {
mutableStateOf(true)
}

Box(modifier = modifier.fillMaxSize()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(Color.LightGray)
)
if (visible) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(MaterialTheme.colorScheme.primary)
)
}
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(Color.LightGray)
)
Button(
// toggle visible state
onClick = { visible = !visible },
modifier = Modifier
.padding(top = 32.dp)
) {
Text(text = "Toggle Visible")
}
}
}
}

To see how this code functions without animation, view the following video on YouTube Shorts:

So, how do we introduce animations to these visibility changes? While there are several methods, I’ll demonstrate the simplest approach using AnimatedVisibility().

AnimatedVisibility() takes a Boolean value to control the visibility state and automatically applies animations to elements within its scope. For more details on AnimatedVisibility, you can refer to the official documentation.

Below is an example illustrating how to add simple animations with AnimatedVisibility:

@Composable
fun AnimatedVisibilityEx(modifier: Modifier = Modifier) {

// visible state
var visible by remember {
mutableStateOf(true)
}

Box(modifier = modifier.fillMaxSize()) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(Color.LightGray)
)
// Enable to animate
AnimatedVisibility(visible = visible) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(MaterialTheme.colorScheme.primary)
)
}
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(Color.LightGray)
)
Button(
// toggle visible state
onClick = { visible = !visible },
modifier = Modifier
.padding(top = 32.dp)
) {
Text(text = "Toggle Visible")
}
}
}
}

Remarkably, just like that, the visibility animations work as expected! To see the animated result, watch the following video on YouTube Shorts:

In the upcoming section, we’ll explore how to customize animations using AnimatedVisibility.

☛ Customizing Animations

AnimatedVisibility offers additional parameters beyond the visibility parameter, allowing for more control over animations. You can customize the animation for when an element becomes visible by modifying the enter parameter. Likewise, for when an element becomes invisible, adjustments can be made to the exit parameter. In this part of the article, we'll focus on customizing the animation for when the state changes to invisible, which involves setting values for the exit parameter.

By specifying slideOutHorizontally(), the exit animation will slide out horizontally. Additionally, using shrinkVertically() will animate the change in height.

Below is a snippet of code related to customizing animations:

// Enable to animate
AnimatedVisibility(
visible = visible,
exit = slideOutHorizontally(
targetOffsetX = { -it },
animationSpec = tween(durationMillis = 300)
) + shrinkVertically(
animationSpec = tween(delayMillis = 300)
)
) {
// Animated Composable
}

As demonstrated, you can combine multiple animations using the + operator. To see this code's animation in action, watch the following video on YouTube Shorts:

While animations are crucial for enhancing an app’s quality, it’s important to remember the purpose behind adding them. Always use animations judiciously and ensure they contribute positively to the user experience, rather than simply being decorative or distracting.

<aside>
<p>
Thank you for reading!<br>
If you enjoyed this post, <br>
I'd appreciate a clap. 😄
</p>
</aside>

--

--