Integrating Lottie Animations into Mobile Applications
The designer delivered a .json file from After Effects via the Bodymovin plugin. Seems simple: add LottieAnimationView to layout, point to the file, done. In reality, first testing reveals: animation jitters on Xiaomi with Android 9, won't play on Samsung with API 21, and on iOS consumes 40 MB on a single loading screen.
What Goes Wrong with Basic Integration
lottie-android from version 6.x requires API 21 minimum, but full Bodymovin effect support only starts at API 26+. Gradients, masks, track mattes—on API 21–25, some effects render via Canvas instead of hardware acceleration. Result: FPS drops from 60 to 15 on mid-range devices with complex animation.
iOS has a similar trap: lottie-ios 4.x uses CoreAnimation layers for most effects, but with merge paths or complex masks, it switches to CALayer with software rendering. This isn't obvious from docs—you only realize it when Instruments show CoreGraphics instead of Metal in GPU utilization.
Another problem source is .json file size. A three-screen onboarding animation can weigh 800 KB–2 MB if the designer forgot to remove unused assets or exported with raster images inside JSON (base64-encoded). Parsing a two-megabyte JSON on the main thread at startup causes noticeable cold start delay.
Correct Integration
Android (Kotlin):
// build.gradle
implementation "com.airbnb.android:lottie:6.4.0"
val animationView = LottieAnimationView(context)
animationView.setAnimation(R.raw.loading_animation) // from res/raw
animationView.repeatCount = LottieDrawable.INFINITE
animationView.enableMergePathsForKitKatAndAbove(true) // API 19+
animationView.play()
enableMergePathsForKitKatAndAbove(true) enables software rendering of merge paths on older APIs—without it, some animations simply don't display correctly. For performance-critical cases, use setRenderMode(RenderMode.HARDWARE) for forced hardware-accelerated rendering.
iOS (Swift):
// Package.swift or SPM: com.airbnb.ios/lottie-ios 4.x
import Lottie
let animationView = LottieAnimationView(name: "loading_animation")
animationView.loopMode = .loop
animationView.contentMode = .scaleAspectFit
animationView.play()
For SwiftUI, use LottieView from lottie-ios 4.2+:
LottieView(animation: .named("loading_animation"))
.playing(.toProgress(1, loopMode: .loop))
JSON optimization: before integration, run through LottieFiles Optimizer or lottie-compress CLI. Typical result is 40–60% size reduction with no quality loss. Replace raster images inside JSON with external file links via imagesDictionary.
Flutter:
// pubspec.yaml: lottie: ^3.1.0
Lottie.asset(
'assets/animations/loading.json',
repeat: true,
fit: BoxFit.contain,
)
In Flutter, LottieBuilder caches the decoded LottieComposition—important to reuse via LottieComposition.cache when the same animation appears multiple times.
Timeline
Basic integration of a single Lottie animation on one platform takes 2–3 hours including testing and optimization. Multiple animations or both-platform integration with code control (pause, seek, completion callbacks) takes half a day to a full day. Cost is calculated individually.







