DEV Community

Maria Luíza
Maria Luíza

Posted on

3

Animation Component with Compose

firebase icon

Hello, amazing person of the internet! Hope you're doing well.

As users become increasingly accustomed to fluid animations and intuitive interactions, incorporating animation into your app has become a pivotal element for success.

 

Animate*AsState

This API should be used when animating State changes. Let’s see how we can do this in practice.

You just need to declare your variable as animate*AsState. In my case, I am going to animate a color:

I am simply setting a color with the color variable, and the backgroundColor that we are going to use is declared using animateColorAsState, which takes the color as a parameter.

Now, let’s create two buttons, and upon clicking them, we will set another value to the color variable:

var color by remember {
mutableStateOf(Pink80)
}
val backgroundColor by animateColorAsState(color)
view raw MainActivity.kt hosted with ❤ by GitHub

You are going to see something like that:

gif of a phone showing the color change

 

Animating Content Size

Expanding the content of a component is not a surprise to us, but you can make it even prettier by adding some animation.

You just need to add animateContentSize to the modifier of your card

Here is my card without any animation. It simply expands when you click on it:

Button(
modifier = Modifier.padding(
horizontal = 16.dp,
vertical = 4.dp
),
onClick = {
color = Pink80
}
) {
Text(text = "Color 01")
}
Button(
modifier = Modifier.padding(
horizontal = 16.dp,
vertical = 4.dp
),
onClick = {
color = Purple40
}
) {
Text(text = "Color 02")
}
view raw MainActivity.kt hosted with ❤ by GitHub

gif of a phone showing a card

To animate, I am going to call the animateContentSize on the modifier's column:

Surface(
modifier = Modifier
.fillMaxWidth(),
onClick = onClick
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.animateContentSize()
) {
Row {
Icon(
imageVector = Icons.Default.Info,
contentDescription = null
)
Spacer(modifier = Modifier.width(16.dp))
Text(
text = topic,
style = MaterialTheme.typography.bodyMedium
)
}
if (expanded) {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
textAlign = TextAlign.Justify
)
}
}
}
view raw Card.kt hosted with ❤ by GitHub

gif of a phone showing a card

 

Animating Visibility

I love how it’s easy to create animated views with Jetpack Compose. Have you ever wondered how to animate elements when scrolling through a list? Let’s do this.

First things first, I am going to create a lazy column list. If you don’t know how to develop this, just check out my article about list and grid layouts:

val lazyListState = rememberLazyListState()
LazyColumn(
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 32.dp),
state = lazyListState,
modifier = Modifier.padding(paddingValues)
){
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
}
view raw MainActivity.kt hosted with ❤ by GitHub

To create animated visibility, we can utilize The AnimatedVisibility method. This method triggers the animation component each time the associated Boolean value changes.

I’m going to animate two components: a floating action bar and a text. Let’s create a function responsible for animating each of these views:

@Composable
fun FloatingActionButton(
extended: Boolean,
onClick: () -> Unit
) {
FloatingActionButton(onClick = {
onClick
}) {
Row(modifier = Modifier.padding(horizontal = 16.dp)) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Adding floating action button"
)
AnimatedVisibility(extended) {
Text(
text = "Add",
modifier = Modifier.padding(start = 8.dp, top = 3.dp)
)
}
}
}
}
@Composable
fun AnimatedMessage(
extended: Boolean
) {
AnimatedVisibility(
visible = extended,
exit = slideOutHorizontally(
targetOffsetX = { fullWidth: Int -> fullWidth }
),
enter = slideInHorizontally(
initialOffsetX = { fullWidth: Int -> fullWidth }
)
) {
Surface(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "Add an item to the list",
modifier = Modifier.padding(16.dp)
)
}
}
}

visible: Set this to determine if the animation should occur or not.
exit: Use it to control how the animation occurs when the component is disappearing.
enter: Use it to control how the animation occurs when the component is appearing.
Now, let’s call those functions in our main activity using the scaffold methods.

First, the floating action button :

Scaffold(
floatingActionButton = {
FloatingActionButton(
extended = lazyListState.isScrollInProgress,
onClick = {
coroutineScope.launch {
showMessage()
}
}
)
}
view raw MainActivity.kt hosted with ❤ by GitHub

Now, let’s refer to the animated text in the content parameter:

val lazyListState = rememberLazyListState()
Scaffold(
floatingActionButton = {
FloatingActionButton(
extended = lazyListState.isScrollInProgress,
onClick = {
coroutineScope.launch {
showMessage()
}
}
)
},
content = { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.background(backgroundColor)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
AnimatedMessage(lazyListState.isScrollInProgress)
view raw MainActivity.kt hosted with ❤ by GitHub

Last but not least, let’s call the list:

Scaffold(
floatingActionButton = {
FloatingActionButton(
extended = lazyListState.isScrollInProgress,
onClick = {
coroutineScope.launch {
showMessage()
}
}
)
},
content = { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.background(backgroundColor)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
LazyColumn(
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 32.dp),
state = lazyListState,
modifier = Modifier.padding(paddingValues)
){
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
item { Text(text = "Scroll here") }
item { Spacer(modifier = Modifier.height(16.dp)) }
}
}
)
view raw MainActivity.kt hosted with ❤ by GitHub

gif of a phone showing a card

 

Conclusion

There are many other animations you can create with Compose.

If you all are interested, I can demonstrate and provide those customization.

integrating animation directly into Compose, it simplifies the process and optimizes performance. Embracing this technology opens up a world of creative possibilities and enhances the user experience, ensuring a promising future for Android UI development.

All the code and exemple it is on this repository.

Happy coding ❤


Please let me know what you think in the comments…

Connect with me 👇

Linkedin

GitHub

Instagram

Medium

git of a woman

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • --last-failed: Zero in on just the tests that failed in your previous run
  • --only-changed: Test only the spec files you've modified in git
  • --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Practical examples included!

Watch Video 📹️

👋 Kindness is contagious

If you found this article helpful, please give a ❤️ or share a friendly comment!

Got it