Mastering Animations in Jetpack Compose: A Comprehensive Guide
Animation brings life to your Android applications, transforming static UIs into dynamic, engaging experiences. In this comprehensive guide, we'll explore the powerful animation capabilities of Jetpack Compose, breaking down different types of animations, their implementations, and best practices.
1. Understanding Animation Basics
Before diving into specific implementations, it's crucial to understand that Compose animations are declarative and type-safe. They automatically handle interruptions and changes in animated values, making them more robust than traditional imperative animations.
Core Animation Properties :
Value: The animated property (size, position, color, etc.)
Duration: How long the animation runs
Easing: The rate of change over time
Delay: Time before animation starts
Repeat: Whether and how the animation repeats
2. Types of Animations
Scale Animations : Scale Animation Scale animations modify the size of components, perfect for emphasis or feedback.
var isExpanded by remember { mutableStateOf(false) }
val scale by animateFloatAsState(
targetValue = if (isExpanded) 2f else 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
)
)
Box(
modifier = Modifier
.graphicsLayer(
scaleX = scale,
scaleY = scale
)
)
Translation Animation: Translation animations move components across the screen.
val offset by animateFloatAsState(
targetValue = if (isOffset) 100f else 0f,
animationSpec = tween(
durationMillis = 1000,
easing = FastOutSlowInEasing
)
)
Box(
modifier = Modifier.offset(x = offset.dp)
)
Rotation Animation: Rotation animations spin components around their axis.
val rotation by rememberInfiniteTransition().animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(2000, easing = LinearEasing),
repeatMode = RepeatMode.Restart
)
)
Box(
modifier = Modifier.graphicsLayer(rotationZ = rotation)
)
Alpha Animation: Alpha animations modify transparency.
val alpha by animateFloatAsState(
targetValue = if (isVisible) 1f else 0f,
animationSpec = tween(durationMillis = 300)
)
Box(
modifier = Modifier.graphicsLayer(alpha = alpha)
)
Color Animation: Color animations smoothly transition between colors.
val color by animateColorAsState(
targetValue = if (isSelected) Color.Red else Color.Blue,
animationSpec = tween(durationMillis = 500)
)
Box(
modifier = Modifier.background(color)
)
3. Animation APIs and Methods
Animation Methods
1. animateXxxAsState
For single-value animations
Automatically handles interruptions
Returns State
rememberInfiniteTransition
For continuous animations
Perfect for loading indicators or background effects
updateTransition
For managing multiple animations together
Coordinates timing between animations
4. AnimatedVisibility
For enter/exit animations
Includes predefined transitions
Animation Specifications
tween: Linear animation with customizable duration and easing
spring: Physics-based animation with natural movement
snap: Immediate value change
keyframes: Complex animations with multiple steps
Here's a flowchart showing the decision process for choosing the right animation API:
4. Gesture-Based Animations
Compose provides powerful gesture handling combined with animations:
var offsetX by remember { mutableFloatStateOf(0f) }
val draggableState = rememberDraggableState { delta ->
offsetX += delta
}
Box(
modifier = Modifier
.offset { IntOffset(offsetX.roundToInt(), 0) }
.draggable(
state = draggableState,
orientation = Orientation.Horizontal,
onDragStopped = { velocity ->
// Add spring animation here
}
)
)
5. Real-World Example Analysis
lLet's create a simple app that demonstrates a scaling, floating, and rotating rainbow border animation using the built-in APIs. The app will look something like this:
The main idea is that when the app starts, "HELLO!" will appear to bulge out of the screen and then return to normal. When the user clicks on the word, fish will slide horizontally. Clicking the button will make a new screen fade in, showing a circular image with a rotating background. Additionally, if the user clicks on the jellyfish, its eyes will appear and disappear with each click.
1. Floating Animation (JellyFish)
val translationY = rememberInfiniteTransition()
val animatedOffset by translationY.animateFloat(
initialValue = -10f,
targetValue = 10f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 800),
repeatMode = RepeatMode.Reverse
)
)
This creates a smooth floating effect using infinite animation.
2. Scale Animation (Hello Text)
val scale by animateFloatAsState(
targetValue = if (!shouldStartAnimation) 0f
else if (!isAnimationPlayed) 2.5f
else 1f,
animationSpec = spring(
dampingRatio = 0.6f,
stiffness = Spring.StiffnessLow
)
)
This creates a bouncy entrance effect.
3. Rainbow Border Animation
var rotationAngle by remember { mutableFloatStateOf(0f) }
LaunchedEffect(Unit) {
while (true) {
delay(16)
rotationAngle = (rotationAngle + 0.8f) % 360f
}
}
This creates a rotating rainbow border effect.
full link to the project:
additionally, you can also check out the official Android documentation for animations in Compose to dive deep into the topic.
link to the documentation:
Subscribe to my newsletter
Read articles from Aditya Das directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Aditya Das
Aditya Das
B.Tech student in Information Technology with a passion for Android app development. Specializing in Kotlin, Java, and modern development practices. Exploring the latest trends in mobile and web technologies, and committed to sharing knowledge and insights through blogging. Follow along for tutorials, tips, and industry updates!