Bring Your UI to Life with Lottie Animations in Jetpack Compose
Want to add engaging animations to your app? Lottie animations are the way to go! They bring smooth, scalable animations to your UI with minimal effort. In Jetpack Compose, integrating Lottie is simple using the LottieAnimation
composable. Below, we’ll show you how to use Lottie animations with interactive controls like play, pause, speed, scale, rotation, and more.

Quick Peek: What You'll See Here
We’ll use a Lottie animation with success, failure, and looping states, controlled by buttons for play/pause, speed, scale, rotation, and opacity. Each example includes code you can copy and explanations of why it works. Let’s dive in!
1. Basic Lottie Animation Setup
Load a Lottie animation from a raw resource and display it with default settings. This is the foundation for all Lottie animations in Compose.
@Composable
fun BasicLottieAnimation() {
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.anim_loading_success_failed))
LottieAnimation(
composition = composition,
progress = { animateLottieCompositionAsState(composition).value },
modifier = Modifier.size(320.dp).padding(16.dp)
)
}
Why Try It: Uses rememberLottieComposition
to load the animation and LottieAnimation
to display it. Perfect for simple animations like loading spinners.
2. Interactive Animation Controls
Add buttons to control play/pause, success, and failure states, with custom animation ranges for each state.
@Composable
fun InteractiveLottieAnimation() {
var lottieState by remember { mutableStateOf(LottieState()) }
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.anim_loading_success_failed))
val progress by animateLottieCompositionAsState(
composition = composition,
iterations = if (lottieState.isSuccess || lottieState.isFailed) 1 else LottieConstants.IterateForever,
isPlaying = lottieState.isPlaying,
clipSpec = LottieClipSpec.Progress(
min = if (lottieState.isFailed) 0.499f else 0.0f,
max = when {
lottieState.isSuccess -> 0.44f
lottieState.isFailed -> 0.95f
else -> 0.282f
}
)
)
Column(
modifier = Modifier.fillMaxSize().background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally
) {
LottieAnimation(
composition = composition,
progress = { progress },
modifier = Modifier.size(320.dp).padding(16.dp)
)
Row(
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
SimpleButton("Play Full", Icons.Default.PlayArrow) {
lottieState = lottieState.copy(isPlaying = true, isSuccess = false, isFailed = false)
}
SimpleButton("Success", Icons.Default.Check) {
lottieState = lottieState.copy(isPlaying = true, isSuccess = true, isFailed = false)
}
}
Row(
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
SimpleButton("Failure", Icons.Default.Close) {
lottieState = lottieState.copy(isPlaying = true, isSuccess = false, isFailed = true)
}
SimpleButton("Play/Pause", Icons.Default.PlayArrow) {
lottieState = lottieState.copy(isPlaying = !lottieState.isPlaying)
}
}
}
}
Why Try It: Uses LottieClipSpec.Progress
to control specific animation segments. Great for forms or feedback screens.
3. Dynamic Animation Properties
Modify stroke width and opacity dynamically based on animation state for a customized look.
@Composable
fun DynamicLottieAnimation() {
var lottieState by remember { mutableStateOf(LottieState()) }
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.anim_loading_success_failed))
val dynamicProperties = rememberLottieDynamicProperties(
rememberLottieDynamicProperty(
property = LottieProperty.STROKE_WIDTH,
value = if (lottieState.isSuccess) 5f else 2f,
keyPath = arrayOf("**")
),
rememberLottieDynamicProperty(
property = LottieProperty.OPACITY,
value = (lottieState.opacity * 100).toInt(),
keyPath = arrayOf("**")
)
)
LottieAnimation(
composition = composition,
progress = { animateLottieCompositionAsState(composition).value },
modifier = Modifier.size(320.dp).padding(16.dp),
dynamicProperties = dynamicProperties
)
}
Why Try It: rememberLottieDynamicProperties
lets you tweak animation visuals. Ideal for emphasizing states like success or failure.
4. Animated Scale and Rotation
Add smooth scale and rotation effects to the animation with spring and tween animations.
@Composable
fun AnimatedLottieTransform() {
var lottieState by remember { mutableStateOf(LottieState()) }
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.anim_loading_success_failed))
val scaleAnimation by animateFloatAsState(
targetValue = lottieState.scale,
animationSpec = tween(durationMillis = 500, easing = LinearEasing)
)
val rotationAnimation by animateFloatAsState(
targetValue = lottieState.rotation,
animationSpec = spring(dampingRatio = Spring.DampingRatioLowBouncy)
)
Column(
modifier = Modifier.fillMaxSize().background(Color.White),
horizontalAlignment = Alignment.CenterHorizontally
) {
LottieAnimation(
composition = composition,
progress = { animateLottieCompositionAsState(composition).value },
modifier = Modifier
.size(320.dp)
.padding(16.dp)
.graphicsLayer(
scaleX = scaleAnimation,
scaleY = scaleAnimation,
rotationZ = rotationAnimation,
transformOrigin = TransformOrigin.Center
)
)
Row(
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
SimpleButton("Scale", Icons.Default.Add) {
lottieState = lottieState.copy(scale = if (lottieState.scale == 1f) 1.5f else 1f, isPlaying = true)
}
SimpleButton("Rotate", Icons.Default.Refresh) {
lottieState = lottieState.copy(rotation = if (lottieState.rotation == 0f) 360f else 0f, isPlaying = true)
}
}
}
}
Why Try It: Combines animateFloatAsState
with graphicsLayer
for smooth transformations. Perfect for interactive UI elements.
Which One's Best? A Quick Comparison
Here’s how the Lottie animation approaches compare, ranked by versatility and impact.
Add Dynamic Lottie Animations in Jetpack ComposeLottie animations bring your app to life with smooth, engaging visuals. Using Jetpack Compose, you can easily integrate animations with interactive controls like play, pause, speed, scale, and opacity. Let’s explore how to implement a Lottie animation with a loading, success, and failure sequence. ![]() What’s Covered HereWe’ll use a Lottie animation with controls to toggle states (loading, success, failure), adjust speed, scale, rotation, and opacity. Each example includes copyable code and explanations. Let’s get started! 1. Basic Lottie AnimationLoad and display a Lottie animation from a raw resource with default looping.
Why Try It: Simple setup with 2. Interactive State ControlsAdd buttons to switch between loading, success, and failure states with specific animation ranges.
Why Try It: Controls animation segments with 3. Dynamic Visual AdjustmentsDynamically change stroke width and opacity based on animation state.
Why Try It: 4. Scale and Rotation EffectsApply smooth scale and rotation animations to enhance the Lottie visual.
Why Try It: Uses Which Approach is Best?Here’s a ranked comparison of the Lottie animation approaches.
Tips for Using Lottie in Jetpack Compose
Common QuestionsHow Do I Add Lottie to My Project?Add the Lottie Compose dependency: Can I Use Lottie for Buttons?Yes! Place Where to Find Lottie Files?Check LottieFiles for free, high-quality animations. Full Code to Copy and RunHere’s the complete code for the Lottie animation demo. Paste it into your project to see it in action!
Paste this into your Jetpack Compose project to see the full Lottie animation demo in action! |
---|