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

Vector Scalable Efficient
🎬

Professional Quality

After Effects animations

Smooth Complex Beautiful
🌐

Free Resources

Thousands of free animations

LottieFiles Community Ready-made
🎮

Full Control

Play, pause, and control animations

Interactive Dynamic Controllable

🔹 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

🧠 Test Your Knowledge

What file format do Lottie animations use?