Add the dependency to your project build.gradle
file:
dependencies {
...
implementation "com.airbnb.android:lottie-compose:$lottieVersion"
...
}
Snapshots are hosted on Sonatype. First, add the Sonatype repository to your build.gradle
file:
allprojects {
repositories {
...
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
}
The latest snapshot version is:
@Composable
fun Loader() {
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.loading))
val progress by animateLottieCompositionAsState(composition)
LottieAnimation(
composition = composition,
progress = { progress },
)
}
Or with the LottieAnimation
overload that merges LottieAnimation
and animateLottieCompositionsState()
@Composable
fun Loader() {
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.loading))
LottieAnimation(composition)
}
LottieComposition
is the parsed version of your Lottie json file. It is stateless and can be cached/reused freely.
To create a LottieComposition
:
- Use
rememberLottieComposition(spec)
- Pass in a
LottieCompositionSpec
.LottieCompositionSpec
is a sealed class that lets you select the source (res/raw, assets, string, network, etc.).
For example:
val composition1 by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.animation))
val composition2 by rememberLottieComposition(LottieCompositionSpec.Url("https://..."))
// src/main/assets/animations/animation.json
val composition3 by rememberLottieComposition(LottieCompositionSpec.Asset("animations/animation.json"))
The type returned from rememberLottieComposition(spec)
is
interface LottieCompositionResult : State<LottieComposition?>
This allows you to use it in two ways:
val composition: LottieComposition? by rememberLottieComposition(spec)
This will return null until the composition is parsed and then will return the LottieComposition
object.
Use this version in most cases, especially if you don't need any of the extra functionality on LottieCompositionResult
.
val compositionResult: LottieCompositionResult = rememberLottieComposition(spec)
LottieCompositionResult
lets you:
- Access the composition via
compositionResult.value
- Access
error
,isLoading
,isComplete
,isFailure
, andisSuccess
properties. - Call
await()
to await the parsed composition from a coroutine.
In most cases, you shouldn't expect parsing to fail. However, if you are loading an animation from the network or loading an animation from a file without the correct permissions, it may fail. To handle failures and retries:
val retrySignal = rememberLottieRetrySignal()
val composition by rememberLottieComposition(
LottieCompositionSpec.Url("not a url"),
onRetry = { failCount, exception ->
retrySignal.awaitRetry()
// Continue retrying. Return false to stop trying.
true
}
)
Then, you can call retrySignal.retry()
from something like a click listener to retry loading.
LottieAnimation
is the primary Lottie composable. It's parameters include:
- The
LottieComposition
that should be rendered (or null if it hasn't been loaded or parsed yet). - The progress that should be rendered. Driving the animation progress is decoupled from the composable so that you can either use Lottie's animation utilities or create your own based on other animation sources or app state like download progress or gestures.
- Render settings such as speed, dynamic properties, images, render mode (hardware or software), etc.
You have the option of handling progress entirely yourself. If you choose to do that, just pass in progress
to your LottieAnimation
composable.
In most cases, you will want to use either animateLottieCompositionAsState()
or LottieAnimatable
. These APIs were designed to be analogous to the standard Jetpack Compose APIs. animateLottieCompositionAsState
is analogous to animate*AsState and LottieAnimatable
is analogous to Animatable.
The decision for whether to use one over the other is similar as well:
- If your animation is very simple or a function of other state properties, use
animateLottieCompositionAsState()
. - If you need to imperatively call
animate
orsnapTo
from something like aLaunchedEffect
then useLottieAnimatable
.
animateLottieCompositionAsState()
returns and LottieAnimatable
implements:
interface LottieAnimationState : State<Float>
val progress by animateLottieCompositionAsState(composition)
val progress by animateLottieCompositionAsState(
composition,
iterations = LottieConstants.IterateForever,
)
val progress by animateLottieCompositionAsState(
composition,
clipSpec = LottieClipSpec.Progress(0.5f, 0.75f),
)
There is an overloaded version of the LottieAnimation
composable that merges the LottieAnimation
and animateLottieCompositionAsState
parameters.
LottieAnimation(
composition,
iterations = LottieConstants.IterateForever,
clipSpec = LottieClipSpec.Progress(0.5f, 0.75f),
)
@Stable
class MyHoistedState {
val lottieAnimatable = LottieAnimatable()
val somethingElse by mutableStateOf(0f)
}
val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.animation))
val lottieAnimatable = rememberLottieAnimatable()
LaunchedEffect(Unit) {
lottieAnimatable.animate(
composition,
iterations = LottieConstants.IterateForever,
clipSpec = LottieClipSpec.Progress(0.5f, 0.75f),
)
}
Images should be avoided whenever possible. They are much larger, less performant, and can lead to pixelation. Whenever possible, try and make your animation consist solely of vectors. However, Lottie does support images in one of 4 ways:
- Baked into the Lottie json file. This is done via an option in the exporter (such as teh Bodymovin After Effects plugin). When done, images are encoded as a base64 string and embedded directly in the json file. This is the simplest way to use images because everything is contained in a single file and no additional work is necessary to make them work.
- Zipped with the json file in a single zip file. When parsing the animation, Lottie will unzip the animation and automatically link any images in zip file to the composition. These zip files can be stored in
src/main/assets
and loaded viaLottieCompositionSpec.Asset
or downloaded via the internet and loaded viaLottieCompositionSpec.Url
. - Stored in
src/main/assets/*
. When the animation is exported, it may include references to external images referenced via their file name. When this method is used, the images should be stored in a subdirectory within your assets folder and set via theimageAssetsFolder
parameter on yourLottieAnimation
composable. - Via
LottieProperty.IMAGE
dynamic properties.
Lottie allows you to update Lottie animation properties at runtime. Some reasons you may want to do this are:
- Change colors for day/night or other app theme.
- Change the progress of a specific layer to show download progress.
- Change the size and position of something in response to a gesture.
To use dynamic properties, you need 3 things:
- a
LottieProperty
. These are static constants that represent what you are trying to change. The type of the property represents the type that you will return to Lottie to update its value. For example,LottieProperty.OPACITY
is anInteger
and accepts values 0-100. - A
KeyPath
. A KeyPath is a path to the animation node that has the property that you want to animate. Refer to the docs forKeyPath
on how to construct one. - A
LottieValueCallback
that will get called on each frame or a single value that will be returned on every frame until you update it.
You use those three to construct a LottieDynamicProperties
object like this:
val dynamicProperties = rememberLottieDynamicProperties(
rememberLottieDynamicProperty(
property = LottieProperty.COLOR,
value = color.toArgb(),
keyPath = arrayOf(
"H2",
"Shape 1",
"Fill 1",
)
),
)
and pass it as a parameter to your LottieAnimation
composable.
You can chain together multiple dynamic properties if you want to update several at the same time. This example changes the heart color of heart.json and can also be seen in these examples.