Ever felt your Flutter app’s UI was a bit… static? Want to add that extra touch of polish and delight? Lottie animations are your secret weapon. These lightweight, vector-based animations can transform a mundane interface into an engaging and delightful experience. This comprehensive guide will equip you with the knowledge and practical skills to seamlessly integrate Lottie into your Flutter projects, from basic implementation to advanced techniques.
Source code:
This repository showcases a demo application using Flutter and Lottie animations. It's designed to help you integrate stunning animations seamlessly into your Flutter apps.
Check out the repository on GitHub: Flutter Lottie Demo
Why Lottie? The Magic Behind the Motion
Lottie animations, powered by the Bodymovin library, are JSON files exported from Adobe After Effects. They contain vector-based animation data, offering several key advantages:
- Tiny Footprint, Big Impact: Lottie files are significantly smaller than GIFs or video files, reducing your app’s size and improving load times.
- Scalability Without Limits: Being vector-based, Lottie animations scale flawlessly across different screen sizes and resolutions without any pixelation.
- Performance that Pops: Lottie animations are hardware-accelerated, ensuring smooth and efficient rendering even on less powerful devices.
- Cross-Platform Harmony: Lottie works seamlessly across iOS, Android, and Web, perfectly aligning with Flutter’s cross-platform philosophy.
Getting Started: Integrating Lottie into Your Flutter Project
The lottie package is your gateway to Lottie magic in Flutter. Here's how to get started:
- Install the Package:
flutter pub add lottie
- Import the Necessary Library:
import 'package:lottie/lottie.dart';
- Displaying Your First Lottie Animation:
Lottie.asset('assets/animations/your_animation.json'),
Remember to add your animation JSON file to your assets folder and declare it in your pubspec.yaml:
assets:
- assets/animations/
Unlocking Advanced Lottie Features
The Lottie package offers a wealth of features for customizing and controlling your animations:
- Controlling Animation Flow (Looping, Reversal):
Lottie.asset('assets/animations/your_animation.json', repeat: false), // Plays once
Lottie.asset('assets/animations/your_animation.json', reverse: true), // Plays in reverse
- Taking Control with LottieController: For precise control over animation playback, use a LottieController:
late final LottieController _controller;
@override
void initState() {
super.initState();
_controller = LottieController(vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
// In your build method:
Lottie.asset(
'assets/animations/your_animation.json',
controller: _controller,
onLoaded: (composition) {
_controller.addStatusListener((status) {
if (status == LottieStatus.completed) {
// Animation finished
}
});
_controller.duration = composition.duration;
_controller.forward(); // Start the animation
},
),
// Example of manual control:
ElevatedButton(
onPressed: () => _controller.animateTo(const Duration(milliseconds: 500)),
child: const Text("Go to halfway"),
),
ElevatedButton(
onPressed: () => _controller.reverse(),
child: const Text("Reverse"),
),
ElevatedButton(
onPressed: () => _controller.stop(),
child: const Text("Stop"),
),
Example: Interactive Like Button with Lottie Animation (Beginner-Friendly Explanation — Focused on Lottie)
This example demonstrates how to use Lottie animations in a Flutter app to create an interactive like button. It covers:
- Showing a main animation: This animation changes based on whether the button has been liked.
- Creating an animated like button: When tapped, a small animation plays within the button.
Code Explanation (Focused on Lottie Logic):
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
// ... (MyApp class - Basic app setup - not explained in detail)
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
// 1. Animation Control and State
late final AnimationController _likeController; // Controls the like button's animation
bool isLiked = false; // Tracks if the button is liked (true) or not (false)
bool _likeLottieLoaded = false; // Checks if the like animation file is loaded
@override
void initState() {
super.initState();
_likeController = AnimationController(vsync: this); // Initialize the animation controller
}
@override
void dispose() {
_likeController.dispose(); // Important: Cleans up the controller to prevent issues
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
// ... (App bar - Basic UI element - not explained in detail)
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 2. Main (Center) Animation: Conditional Display
Material( // Provides styling (shadow, rounded corners)
child: isLiked // This decides which animation to show
? Column( // Shows the "Thanks" animation
children: [
Lottie.asset(
'assets/animations/thanks.json', // Path to your "thanks" Lottie file
width: 120,
height: 120,
errorBuilder: (context, error, stackTrace) =>
const Text('Error loading animation!'), // Handles loading errors
),
const SizedBox(height: 16),
const Text(
'Thank You!',
style: TextStyle(
fontSize: 18, color: Colors.green),
),
],
)
: Column( // Shows the "Loading" animation
children: [
Lottie.asset(
'assets/animations/loading.json', // Path to your "loading" Lottie file
width: 120,
height: 120,
repeat: true, // Makes the loading animation loop
errorBuilder: (context, error, stackTrace) =>
const Text('Error loading animation!'), // Handles loading errors
),
const SizedBox(height: 16),
const Text(
'Loading...',
style: TextStyle(
fontSize: 18, color: Colors.grey),
),
],
),
),
const SizedBox(height: 48),
// 3. The Interactive Like Button (with Lottie Animation)
InkWell( // Makes the area clickable
onTap: () { // This code runs when the button is tapped
setState(() {
isLiked = !isLiked; // Toggles the "liked" state (true/false)
if (isLiked && _likeLottieLoaded) { // Only play if the animation is loaded
_likeController.forward().whenComplete(() => _likeController.reset()); // Plays the like animation ONCE
} else if (isLiked && !_likeLottieLoaded) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Animation is still loading")));
}
});
},
child: Stack( // Lets us overlap the animation and text
children: [
// ... (Background styling for the button)
Lottie.asset(
'assets/animations/like.json', // Path to the like animation
controller: _likeController, // Connects the animation to the controller
width: 40,
height: 40,
onLoaded: (composition) { // Called when the Lottie animation is loaded
setState(() {
_likeLottieLoaded = true; // Sets the flag to true
_likeController.duration = composition.duration; // Sets the animation duration
});
},
errorBuilder: (context, error, stackTrace) => const Text('Error loading animation!'), // Handles loading errors
),
// ... (Text for "Like/Liked")
],
),
),
],
),
),
);
}
}
Simplified Explanation of Lottie-Specific Parts:
-
Animation Control and State:
- _likeController: This is like a remote control for the like animation. It tells the animation when to start, stop, etc.
- isLiked: This variable remembers if the button is currently liked or not.
- _likeLottieLoaded: This is a flag to check if the animation file has finished loading. This is important to prevent errors if you try to play the animation before it's ready.
-
Main (Center) Animation: Conditional Display:
- isLiked ? ... : ...: This is a shorthand way of saying "if isLiked is true, do this; otherwise, do that." This is how we switch between the "Thanks" and "Loading" animations.
- Lottie.asset(): This is the widget that displays the Lottie animation. You give it the path to your .json file.
- repeat: true: This makes the loading animation loop continuously.
- errorBuilder: This handles cases where the animation file can't be loaded (e.g., if the path is wrong).
-
The Interactive Like Button (with Lottie Animation):
- onTap: This code runs when the button is tapped.
- setState(): This is essential in Flutter. It tells Flutter to rebuild the parts of the UI that have changed (in this case, isLiked and the animations).
- _likeController.forward().whenComplete(() => _likeController.reset());: This is the core of the like animation. forward() starts the animation. whenComplete() is a function that runs after the animation finishes. Here, we use it to reset() the animation so it can play again the next time the button is tapped. This achieves the "play once" effect.
- ScaffoldMessenger.of(context).showSnackBar: This will display a small message at the bottom of the screen to inform the user that the animation is still loading.
- onLoaded: This is a very important callback. It's called after the Lottie animation file has been completely loaded. Inside this callback, we set _likeLottieLoaded = true to indicate that the animation is ready, and we also set the duration of the animation controller.
- errorBuilder: This handles cases where the animation file cannot be loaded.
Performance Optimization: Keeping Things Smooth
- Simplicity is Key: Complex animations can impact performance. Aim for simpler designs in After Effects.
- Minimize Keyframes: Fewer keyframes mean smaller files and better performance.
- Optimize Images (if used): Compress and optimize any images used within your Lottie animations.
Conclusion: Animate Your Way to a Better UX
Lottie animations offer a fantastic way to enhance your Flutter applications with engaging visuals. By using the Lottie package and following the best practices outlined here, you can create delightful user experiences that set your apps apart.
Top comments (0)