Lottie Animations
Beautiful JSON-based animations in Flutter
🎨 What are Lottie Animations?
Lottie animations are high-quality vector animations exported from Adobe After Effects as JSON files. They're lightweight, scalable, and easy to integrate into Flutter apps, providing professional animations without complex coding or large file sizes.
// Display Lottie animation
Lottie.asset('assets/animation.json')
Lottie Features
Small File Size
JSON files are lightweight
Professional Quality
After Effects animations
Free Resources
Thousands of free animations
Full Control
Play, pause, and control animations
🔹 Installation
Add Lottie package to your project:
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
lottie: ^3.0.0
# Add your animation files
flutter:
assets:
- assets/animations/
Where to find Lottie animations:
- LottieFiles.com: Thousands of free animations
- After Effects: Create custom animations
- Bodymovin: Export plugin for After Effects
🔹 Basic Lottie Animation
Display a simple Lottie animation:
import 'package:lottie/lottie.dart';
class BasicLottieExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Lottie Animation')),
body: Center(
child: Lottie.asset(
'assets/animations/loading.json',
width: 200,
height: 200,
fit: BoxFit.contain,
),
),
);
}
}
// Load from network
class NetworkLottie extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Lottie.network(
'https://assets2.lottiefiles.com/packages/lf20_example.json',
width: 200,
height: 200,
);
}
}
🔹 Controlling Lottie Animations
Play, pause, and control animation playback:
class ControlledLottie extends StatefulWidget {
@override
_ControlledLottieState createState() => _ControlledLottieState();
}
class _ControlledLottieState extends State
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Lottie.asset(
'assets/animations/heart.json',
controller: _controller,
width: 200,
height: 200,
onLoaded: (composition) {
_controller.duration = composition.duration;
},
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => _controller.forward(),
child: Text('Play'),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: () => _controller.stop(),
child: Text('Pause'),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: () => _controller.reset(),
child: Text('Reset'),
),
],
),
],
);
}
}
🔹 Repeating Lottie Animation
Loop animations continuously:
class RepeatingLottie extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Lottie.asset(
'assets/animations/loading.json',
width: 150,
height: 150,
repeat: true, // Loop forever
reverse: false, // Don't reverse
animate: true, // Auto-play
),
),
);
}
}
// Reverse animation
class ReverseRepeatingLottie extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Lottie.asset(
'assets/animations/toggle.json',
repeat: true,
reverse: true, // Play forward then backward
);
}
}
🔹 Interactive Lottie Animation
Trigger animations on user interaction:
class InteractiveLottie extends StatefulWidget {
@override
_InteractiveLottieState createState() => _InteractiveLottieState();
}
class _InteractiveLottieState extends State
with SingleTickerProviderStateMixin {
late AnimationController _controller;
bool isLiked = false;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (isLiked) {
_controller.reverse();
} else {
_controller.forward();
}
setState(() {
isLiked = !isLiked;
});
},
child: Lottie.asset(
'assets/animations/like_button.json',
controller: _controller,
width: 100,
height: 100,
onLoaded: (composition) {
_controller.duration = composition.duration;
},
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
🔹 Loading Indicator with Lottie
Create beautiful loading screens:
class LottieLoadingScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Lottie.asset(
'assets/animations/loading_dots.json',
width: 200,
height: 200,
),
SizedBox(height: 20),
Text(
'Loading...',
style: TextStyle(
fontSize: 18,
color: Colors.grey[600],
),
),
],
),
),
);
}
}
// Success animation
class SuccessAnimation extends StatefulWidget {
@override
_SuccessAnimationState createState() => _SuccessAnimationState();
}
class _SuccessAnimationState extends State
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
void showSuccess() {
_controller.forward().then((_) {
// Navigate or perform action after animation
Future.delayed(Duration(seconds: 1), () {
Navigator.pop(context);
});
});
}
@override
Widget build(BuildContext context) {
return Center(
child: Lottie.asset(
'assets/animations/success_checkmark.json',
controller: _controller,
width: 150,
height: 150,
repeat: false,
onLoaded: (composition) {
_controller.duration = composition.duration;
},
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
🔹 Custom Animation Speed
Control animation playback speed:
class CustomSpeedLottie extends StatefulWidget {
@override
_CustomSpeedLottieState createState() => _CustomSpeedLottieState();
}
class _CustomSpeedLottieState extends State
with SingleTickerProviderStateMixin {
late AnimationController _controller;
double speed = 1.0;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
_controller.repeat();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Lottie.asset(
'assets/animations/car.json',
controller: _controller,
width: 200,
height: 200,
onLoaded: (composition) {
_controller.duration = composition.duration;
},
),
SizedBox(height: 20),
Text('Speed: ${speed.toStringAsFixed(1)}x'),
Slider(
value: speed,
min: 0.5,
max: 3.0,
onChanged: (value) {
setState(() {
speed = value;
_controller.duration = Duration(
milliseconds: (1000 / speed).round(),
);
});
},
),
],
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
💡 Lottie Best Practices:
- File Size: Keep JSON files under 100KB for best performance
- Caching: Lottie automatically caches animations
- Testing: Test animations on real devices for performance
- Fallbacks: Provide static images as fallbacks
- Resources: Use LottieFiles.com for free animations
- Optimization: Simplify complex animations for mobile