Flutter Animations: A Complete Guide with Practical Examples
Animations play a vital role in enhancing the user experience in mobile applications. Flutter, Google’s UI toolkit, makes it incredibly easy to incorporate beautiful animations into your apps. This comprehensive guide will walk you through everything you need to know about Flutter animations, from basics to advanced examples.
Table of Contents
- Introduction to Flutter Animations
- Types of Animations in Flutter
- Implicit Animations
- Explicit Animations
- Tween Animations
- AnimationController and Ticker
- AnimatedBuilder and AnimatedWidget
- Hero Animations
- Staggered Animations
- Custom Animations
- Best Practices
- Full Example: main.dart File
- Conclusion
1. Introduction to Flutter Animations
Flutter animations bring life to your UI, improving both aesthetics and usability. They provide feedback, guide users, and add personality to the app. Flutter supports both simple and complex animations out-of-the-box through a rich set of APIs and widgets.
Why Use Animations?
- Enhance user engagement
- Provide visual feedback
- Improve navigation experience
- Guide user focus
2. Types of Animations in Flutter
Flutter supports two main categories:
Implicit Animations
Widgets that handle animation internally. They’re easier to implement.
Explicit Animations
Gives full control over animation behavior. Requires use of controllers.
3. Implicit Animations
Implicit animations in Flutter are widgets that animate a property change over time.
Common Widgets:
AnimatedContainer
AnimatedOpacity
AnimatedAlign
AnimatedPadding
AnimatedPositioned
AnimatedDefaultTextStyle
Example: AnimatedContainer
AnimatedContainer(
duration: Duration(seconds: 1),
curve: Curves.easeInOut,
width: _width,
height: _height,
color: _color,
child: FlutterLogo(size: 75),
)
Trigger animation by updating the state variables.
4. Explicit Animations
Explicit animations offer more control and flexibility.
Core Components:
AnimationController
Animation
Tween
TickerProvider
Steps:
- Initialize
AnimationController
- Create
Tween
- Use
AnimationBuilder
or custom animated widget
Example:
class MyAnimation extends StatefulWidget {
@override
_MyAnimationState createState() => _MyAnimationState();
}
class _MyAnimationState extends State<MyAnimation>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 0, end: 300).animate(_controller);
_controller.forward();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Container(
width: _animation.value,
height: _animation.value,
color: Colors.blue,
);
},
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
5. Tween Animations
Tween
defines the range of the animation.
Syntax:
Tween<type>(begin: value1, end: value2)
Combine with AnimationController
and animate()
to create smooth interpolations.
Types of Tween:
ColorTween
SizeTween
RectTween
6. AnimationController and Ticker
AnimationController
Drives the animation. Controls duration, speed, and direction.
TickerProvider
Required by AnimationController
to tick frames.
Use SingleTickerProviderStateMixin
or TickerProviderStateMixin
.
7. AnimatedBuilder and AnimatedWidget
AnimatedBuilder
Provides a performance-friendly way to rebuild only parts of the widget tree.
AnimatedWidget
Create custom animated widgets by extending it.
Example with AnimatedBuilder:
AnimatedBuilder(
animation: _animation,
builder: (context, child) => Transform.rotate(
angle: _animation.value,
child: child,
),
child: Icon(Icons.sync, size: 100),
)
8. Hero Animations
Used for seamless screen transitions.
Syntax:
Hero(
tag: 'heroTag',
child: Image.asset('assets/pic.png'),
)
Ensure the same tag
exists on both pages.
Example:
Navigator.push(context, MaterialPageRoute(
builder: (_) => DetailPage(),
));
9. Staggered Animations
Multiple animations with delays. Useful for choreographing UI elements.
Use Case:
Animate multiple properties with delay:
_controller = AnimationController(
duration: Duration(seconds: 4), vsync: this);
heightAnimation = Tween(begin: 0.0, end: 300.0)
.animate(CurvedAnimation(parent: _controller, curve: Interval(0.0, 0.5)));
colorAnimation = ColorTween(begin: Colors.red, end: Colors.green)
.animate(CurvedAnimation(parent: _controller, curve: Interval(0.5, 1.0)));
10. Custom Animations
Build custom animation logic using CustomPainter
, Transform
, or ClipPath
.
CustomPainter Example:
Draw animated shapes based on AnimationController
value.
11. Best Practices
- Use
AnimatedBuilder
to minimize rebuilds. - Dispose controllers in
dispose()
. - Prefer implicit animations for simple transitions.
- Avoid long-running or memory-intensive animations.
- Use
CurvedAnimation
to improve motion realism. - Use
Hero
for cross-screen consistency.
12. Full Example: main.dart File
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: AnimationDemo(),
);
}
}
class AnimationDemo extends StatefulWidget {
@override
_AnimationDemoState createState() => _AnimationDemoState();
}
class _AnimationDemoState extends State<AnimationDemo>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> sizeAnimation;
Animation<Color?> colorAnimation;
bool _visible = true;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
sizeAnimation = Tween<double>(begin: 100, end: 200).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
colorAnimation = ColorTween(begin: Colors.blue, end: Colors.orange).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
_controller.repeat(reverse: true);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Flutter Full Animation Example")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
width: sizeAnimation.value,
height: sizeAnimation.value,
color: colorAnimation.value,
);
},
),
SizedBox(height: 20),
AnimatedOpacity(
duration: Duration(seconds: 1),
opacity: _visible ? 1.0 : 0.0,
child: Text("AnimatedOpacity Text", style: TextStyle(fontSize: 20)),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => setState(() => _visible = !_visible),
child: Text("Toggle Opacity"),
)
],
),
),
);
}
}
13. Conclusion
Animations in Flutter are powerful yet easy to implement. Whether it’s a simple opacity change or a complex staggered motion sequence, Flutter provides the tools needed for a fluid and engaging user experience.
By mastering both implicit and explicit animation techniques, you can elevate your app’s interface from functional to delightful. The more fluently animation is applied, the more polished and professional the final product feels.
Feel free to bookmark this guide and revisit each section as you explore the exciting world of Flutter animations!