Animation In Compose Series (Part 1) — Animated Visiblity and Animated Content

Bharat Kumar
5 min readFeb 20, 2024

--

Hi Devs, I am presenting you my first series of Articles — ANIMATIONS MADE EASY for you.

Animations are an important aspect of a smooth and feel-good App. Animations in Compose have been made very much easier and simpler. So I have bought you the Go-To Guide for Animations in Compose.

Let's start with the basic once First -

Animated Visibility

This is your view.visibility = View.VISIBLE and view.visibility = View.INVISIBLE of Compose.

Simply put, we can make any Composable visible and invisible with this.

Here is how you can use it in the most simple way

   Box(modifier = Modifier.fillMaxSize()) {
var isItemVisible by remember {
mutableStateOf(false)
}
Column(modifier = Modifier.fillMaxWidth()) {
AnimatedVisibility(visible = isItemVisible, modifier = Modifier.size(200.dp)) {
Image(
painter = painterResource(id = R.drawable.kodee),
contentDescription = "Kodee"
)
}
}
Button(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 20.dp),
onClick = { isItemVisible = !isItemVisible }) {
Text(text = "Hide/Unhide")
}
}

Here as you can see isItemVisible is the state used to hide/unhide the Image

Now let’s change the animation here.

AnimatedVisibility(
visibleState = state,
modifier = Modifier.size(200.dp),
enter = fadeIn(),
exit = fadeOut()
) {
Image(
painter = painterResource(id = R.drawable.kodee),
contentDescription = "Kodee"
)
}

Here as you can see we have changed the default animation which is slideIn/slideOut to fadeIn / fadeOut

Now let’s try to change the duration of the animation here.

  AnimatedVisibility(
visibleState = state,
modifier = Modifier.size(200.dp),
enter = fadeIn(animationSpec = tween(3000)),
exit = fadeOut(animationSpec = tween(3000))
) {
Image(
painter = painterResource(id = R.drawable.kodee),
contentDescription = "Kodee"
)
}

Here as you can see we added an Animation duration of 3000ms.

You can do many more things play around with different Enter and Exit animations such as slideIn/slideOut, scaleIn/scaleOut, expandIn/shrinkOut, and much more, and change things accordingly.

A like for this Cute Kitty

Now let's see how to listen to the state of Animation in AnimatedVisibility. AnimatedVisiblity gives us a variant that takes a MutableTransitionState. It is useful for observing the animation state. Let’s see how

    Box(modifier = Modifier.fillMaxSize()) {
val state = remember {
MutableTransitionState(initialState = false).apply {
targetState = true
}
}

Column(modifier = Modifier.fillMaxWidth()) {
AnimatedVisibility(
visibleState = state,
modifier = Modifier.size(200.dp),
enter = fadeIn(animationSpec = tween(2000)),
exit = fadeOut(animationSpec = tween(2000))
) {
Image(
painter = painterResource(id = R.drawable.kodee),
contentDescription = "Kodee"
)
}
}

Column(
modifier = Modifier.align(Alignment.BottomCenter),
horizontalAlignment = Alignment.CenterHorizontally
) {

Text(
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
color = Color.White,
fontSize = 18.sp,
text = when {
state.isIdle && state.currentState -> "Visible"
!state.isIdle && state.currentState -> "Disappearing"
state.isIdle && !state.currentState -> "Invisible"
else -> "Appearing"
}
)
Button(
modifier = Modifier
.padding(bottom = 20.dp),
onClick = { state.targetState = !state.currentState }) {
Text(text = "Hide/Unhide")
}
}
}

As we can see here we can pass a MutableTransitionState listen to the change in States and use them.

I have added a 2-second duration to see the change in States.

Now let’s see how would I animate only once which is a popular question from many devs. Using the above MutableTransitionState you could do that easily.

Box(modifier = Modifier.fillMaxSize()) {
val state = remember {
MutableTransitionState(initialState = false).apply {
targetState = true
}
}

Column(modifier = Modifier.fillMaxWidth()) {
AnimatedVisibility(
visibleState = state,
modifier = Modifier.size(200.dp),
enter = fadeIn(animationSpec = tween(2000)),
exit = fadeOut(animationSpec = tween(2000))
) {
Image(
painter = painterResource(id = R.drawable.kodee),
contentDescription = "Kodee"
)
}
}
}

Just keep the target state as true and don't change the state. That's it. Simple

Done with AnimatedVisiblity let's move on to another.

Animated Content

This is another composable which animates its content as it changes based on a target state.

This Composable is good for —

  1. Animating Something when some state changes.
  2. It can also work as an AnimatedVisiblity composable

Let’s see a basic usage with it first.

 Column(modifier = Modifier.fillMaxSize()) {
var counter by remember {
mutableStateOf(1)
}

AnimatedContent(targetState = counter, label = "Fading counter Animation") {
Text(
text = it.toString(),
fontWeight = FontWeight.Bold,
modifier = Modifier
.fillMaxWidth()
.padding(20.dp),
fontSize = 30.sp
)
}

Button(onClick = { counter++ }) {
Text(text = "Increase Count")
}

}

Here as you can see as soon as the state of the counter changes or the counter value changes the animation is restarted again.

This is best suited for Counter value animations or changes of images and much more.

Let’s see how you can add animations like we added in AnimatedVisiblity

    Column(modifier = Modifier.fillMaxSize()) {
var counter by remember {
mutableIntStateOf(1)
}
AnimatedContent(
targetState = counter,
label = "Fading counter Animation",
transitionSpec = {
fadeIn(tween(2000)) togetherWith fadeOut(tween(2000))
}
) {
Text(
text = it.toString(),
fontWeight = FontWeight.Bold,
modifier = Modifier
.fillMaxWidth()
.padding(20.dp),
fontSize = 30.sp
)
}
Button(onClick = { counter++ }) {
Text(text = "Increase Count")
}
}

Here as you can see we added the animation inside the transitionSpec lambda.

We have an infix function named togetherwith() to combine Enter and Exit animation.

Fade Animation with Animated Content

You can add many more animations and play around with other animations too.

Here is the GitHub repo with samples of Animation — https://github.com/PalankiBharat/Compose-Animation-Samples.git

I am back and will continue writing more and continue this series with more interesting and exciting Animations.

Follow me and Stay tuned for more such content. Feedback would be appreciated as always.

A clap also would be appreciated but a read would be enough.

Thank You and have a Happy coding Journey. :)

You can connect with me at LinkedIn — Bharat Kumar

--

--

Bharat Kumar
Bharat Kumar

Written by Bharat Kumar

Indian Android Developer || Kotlin Enthusiast

No responses yet