DEV Community

Cover image for Lottie Animations in Flutter: Creating Engaging User Experiences
Sayed Ali Alkamel
Sayed Ali Alkamel

Posted on

Lottie Animations in Flutter: Creating Engaging User Experiences

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.

GitHub Repo

Check out the repository on GitHub: Flutter Lottie Demo


lottie logo

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:

  1. Install the Package:
flutter pub add lottie
Enter fullscreen mode Exit fullscreen mode
  1. Import the Necessary Library:
import 'package:lottie/lottie.dart';
Enter fullscreen mode Exit fullscreen mode
  1. Displaying Your First Lottie Animation:
Lottie.asset('assets/animations/your_animation.json'),
Enter fullscreen mode Exit fullscreen mode

Remember to add your animation JSON file to your assets folder and declare it in your pubspec.yaml:

assets:
  - assets/animations/
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • 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"),
),
Enter fullscreen mode Exit fullscreen mode

screenshots of the example app

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:

  1. Showing a main animation: This animation changes based on whether the button has been liked.
  2. 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")
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

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)