The lottie package handles the rendering. Lottie.asset is the simplest way in — add an AnimationController when you need to control playback.
Open pubspec.yaml and add it to dependencies.
dependencies:
flutter:
sdk: flutter
lottie: ^3.0.0Download your icon from Unicorn Icons. Put it in an assets folder and declare it in pubspec.yaml.
flutter:
assets:
- assets/icons/your_icon.jsonThis is the simplest integration — autoplays and loops with no extra code.
import 'package:lottie/lottie.dart';
class MyIcon extends StatelessWidget {
const MyIcon({super.key});
@override
Widget build(BuildContext context) {
return SizedBox(
width: 64,
height: 64,
child: Lottie.asset(
'assets/icons/your_icon.json',
fit: BoxFit.contain,
),
);
}
}Use AnimationController when you need to play on tap, pause, or control speed. Add SingleTickerProviderStateMixin to your StatefulWidget.
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
class ControllableIcon extends StatefulWidget {
const ControllableIcon({super.key});
@override
State<ControllableIcon> createState() => _ControllableIconState();
}
class _ControllableIconState extends State<ControllableIcon>
with SingleTickerProviderStateMixin {
late final AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
_controller.reset();
_controller.forward();
},
child: Lottie.asset(
'assets/icons/your_icon.json',
controller: _controller,
onLoaded: (composition) {
_controller.duration = composition.duration;
_controller.forward();
},
fit: BoxFit.contain,
width: 64,
height: 64,
),
);
}
}Use the controller's repeat and forward methods to drive the animation however you need.
// Loop indefinitely
_controller.repeat();
// Play once forward
_controller.forward();
// Play once, then reverse
_controller.forward().then((_) => _controller.reverse());
// Play at 2x speed
_controller.animateTo(1.0, duration: composition.duration * 0.5);Consider Rive for Flutter
For interactive icons in Flutter, the Rive format is worth a look — GPU-accelerated rendering, smaller files, and built-in state machines for hover and click. Lottie is simpler if you just need a looping animation.
Do I need AnimationController for basic playback?
No. Lottie.asset autoplays and loops by default. Add a controller only when you need to pause, seek, or trigger from app logic.
Lottie or Rive in Flutter?
Rive is better for interactive icons — GPU rendering, smaller files, state machines built in. Lottie is fine for simple looping animations.
How do I play on tap?
Use AnimationController, wrap in GestureDetector, and call _controller.reset(); _controller.forward(); in onTap. Step 4 above shows the full pattern.
Related guides
Get your animated icons
Browse icons ready for Flutter — free to download.