Animations bring life to your Flutter applications, creating engaging and delightful user experiences. This guide covers everything from basic animations to complex, coordinated motion.
Animation Fundamentals
Flutter's animation system is built on several key concepts that work together to create smooth, performant animations.
Core Animation Classes
- AnimationController: Controls the animation's duration and playback
- Tween: Defines the range of values for the animation
- Curve: Determines the animation's easing function
- Animation: The animated value that changes over time
Basic Animation Example
Here's a simple fade-in animation:
class FadeInWidget extends StatefulWidget {
final Widget child;
FadeInWidget({required this.child});
@override
_FadeInWidgetState createState() => _FadeInWidgetState();
}
class _FadeInWidgetState extends State<FadeInWidget>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(milliseconds: 500),
vsync: this,
);
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeIn),
);
_controller.forward();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: _animation,
child: widget.child,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Advanced Animation Techniques
Staggered Animations
Create complex animations by coordinating multiple animated properties:
class StaggeredAnimation extends StatelessWidget {
final Animation<double> controller;
final Animation<double> opacity;
final Animation<double> width;
final Animation<double> height;
StaggeredAnimation({required this.controller})
: opacity = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.0, 0.3, curve: Curves.ease),
),
),
width = Tween<double>(begin: 50.0, end: 200.0).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.3, 0.6, curve: Curves.ease),
),
),
height = Tween<double>(begin: 50.0, end: 200.0).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.6, 1.0, curve: Curves.ease),
),
);
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Opacity(
opacity: opacity.value,
child: Container(
width: width.value,
height: height.value,
color: Colors.blue,
),
);
},
);
}
}
Hero Animations
Create smooth transitions between screens with Hero widgets:
// First Screen
Hero(
tag: 'image-hero',
child: Image.asset('assets/image.png'),
)
// Second Screen
Hero(
tag: 'image-hero',
child: Image.asset('assets/image.png'),
)
Performance Best Practices
- Use const constructors: Reduce widget rebuilds
- Avoid expensive operations: Keep build methods lightweight
- Use RepaintBoundary: Isolate animated widgets
- Profile your animations: Use Flutter DevTools to identify bottlenecks
Custom Implicit Animations
Create reusable animated widgets with ImplicitlyAnimatedWidget:
class AnimatedColorBox extends ImplicitlyAnimatedWidget {
final Color color;
final Widget? child;
AnimatedColorBox({
required this.color,
this.child,
Duration duration = const Duration(milliseconds: 300),
Curve curve = Curves.easeInOut,
}) : super(duration: duration, curve: curve);
@override
AnimatedColorBoxState createState() => AnimatedColorBoxState();
}
class AnimatedColorBoxState
extends AnimatedWidgetBaseState<AnimatedColorBox> {
ColorTween? _colorTween;
@override
void forEachTween(TweenVisitor<dynamic> visitor) {
_colorTween = visitor(
_colorTween,
widget.color,
(value) => ColorTween(begin: value as Color),
) as ColorTween?;
}
@override
Widget build(BuildContext context) {
return Container(
color: _colorTween?.evaluate(animation),
child: widget.child,
);
}
}
Conclusion
Mastering Flutter animations opens up endless possibilities for creating engaging user experiences. Start with simple animations and gradually build up to more complex interactions.
Remember:
- Always dispose of animation controllers
- Use the right animation type for your use case
- Test animations on real devices
- Keep performance in mind