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.LottieCompositionSpecis 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, andisSuccessproperties. - 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
LottieCompositionthat 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
animateorsnapTofrom something like aLaunchedEffectthen 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 the 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/assetsand loaded viaLottieCompositionSpec.Assetor 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 theimageAssetsFolderparameter on yourLottieAnimationcomposable. - Via
LottieProperty.IMAGEdynamic 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.OPACITYis anIntegerand 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 forKeyPathon how to construct one. - A
LottieValueCallbackthat 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.