Flutter Animation Widgets: Creating Dynamic UIs
•12 min read
Animation widgets are essential for creating engaging and dynamic user interfaces in Flutter applications. Let's explore the various animation widgets and how to use them effectively.
1. Basic Animation Widgets
AnimatedContainer
class AnimatedContainerExample extends StatefulWidget { @override _AnimatedContainerExampleState createState() => _AnimatedContainerExampleState(); } class _AnimatedContainerExampleState extends State<AnimatedContainerExample> { bool _isExpanded = false; @override Widget build(BuildContext context) { return GestureDetector( onTap: () { setState(() { _isExpanded = !_isExpanded; }); }, child: AnimatedContainer( duration: Duration(milliseconds: 300), width: _isExpanded ? 200 : 100, height: _isExpanded ? 200 : 100, color: _isExpanded ? Colors.blue : Colors.red, child: Center( child: Text( _isExpanded ? 'Expanded' : 'Tap to expand', style: TextStyle(color: Colors.white), ), ), ), ); } }
AnimatedOpacity
class AnimatedOpacityExample extends StatefulWidget { @override _AnimatedOpacityExampleState createState() => _AnimatedOpacityExampleState(); } class _AnimatedOpacityExampleState extends State<AnimatedOpacityExample> { bool _isVisible = true; @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedOpacity( duration: Duration(milliseconds: 300), opacity: _isVisible ? 1.0 : 0.0, child: Container( width: 200, height: 200, color: Colors.blue, child: Center( child: Text( 'Fade In/Out', style: TextStyle(color: Colors.white), ), ), ), ), SizedBox(height: 20), ElevatedButton( onPressed: () { setState(() { _isVisible = !_isVisible; }); }, child: Text(_isVisible ? 'Hide' : 'Show'), ), ], ); } }
2. Advanced Animation Widgets
Hero
class HeroExample extends StatelessWidget { @override Widget build(BuildContext context) { return GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(), ), ); }, child: Hero( tag: 'hero-tag', child: Container( width: 100, height: 100, color: Colors.blue, child: Center( child: Text( 'Tap me', style: TextStyle(color: Colors.white), ), ), ), ), ); } } class DetailScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Detail Screen'), ), body: Center( child: Hero( tag: 'hero-tag', child: Container( width: 300, height: 300, color: Colors.blue, child: Center( child: Text( 'Hero Animation', style: TextStyle(color: Colors.white), ), ), ), ), ), ); } }
AnimatedBuilder
class AnimatedBuilderExample extends StatefulWidget { @override _AnimatedBuilderExampleState createState() => _AnimatedBuilderExampleState(); } class _AnimatedBuilderExampleState extends State<AnimatedBuilderExample> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 2), vsync: this, )..repeat(reverse: true); _animation = CurvedAnimation( parent: _controller, curve: Curves.easeInOut, ); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _animation, builder: (context, child) { return Transform.rotate( angle: _animation.value * 2 * 3.14159, child: Container( width: 100, height: 100, color: Colors.blue, child: Center( child: Text( 'Rotating', style: TextStyle(color: Colors.white), ), ), ), ); }, ); } }
3. Custom Animation Widgets
Custom Animation Controller
class CustomAnimationController extends StatefulWidget { @override _CustomAnimationControllerState createState() => _CustomAnimationControllerState(); } class _CustomAnimationControllerState extends State<CustomAnimationController> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 1), vsync: this, ); _animation = Tween<double>( begin: 0.0, end: 1.0, ).animate(_controller); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ AnimatedBuilder( animation: _animation, builder: (context, child) { return Transform.scale( scale: _animation.value, child: Container( width: 100, height: 100, color: Colors.blue, child: Center( child: Text( 'Scale', style: TextStyle(color: Colors.white), ), ), ), ); }, ), SizedBox(height: 20), ElevatedButton( onPressed: () { if (_controller.isCompleted) { _controller.reverse(); } else { _controller.forward(); } }, child: Text(_controller.isCompleted ? 'Reverse' : 'Forward'), ), ], ); } }
Custom Animation Widget
class CustomAnimationWidget extends StatefulWidget { final Widget child; final Duration duration; final Curve curve; const CustomAnimationWidget({ required this.child, this.duration = const Duration(milliseconds: 300), this.curve = Curves.easeInOut, }); @override _CustomAnimationWidgetState createState() => _CustomAnimationWidgetState(); } class _CustomAnimationWidgetState extends State<CustomAnimationWidget> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _animation; @override void initState() { super.initState(); _controller = AnimationController( duration: widget.duration, vsync: this, ); _animation = CurvedAnimation( parent: _controller, curve: widget.curve, ); _controller.forward(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return FadeTransition( opacity: _animation, child: widget.child, ); } }
4. Best Practices
-
Implement proper animations
- Choose appropriate animation widgets
- Handle animation states
- Consider performance impact
-
Enhance animation experience
- Add smooth transitions
- Implement proper timing
- Consider user feedback
-
Optimize animation performance
- Use const constructors
- Minimize rebuilds
- Handle memory efficiently
By mastering these animation widgets and following best practices, you can create Flutter applications that are:
- More engaging
- More dynamic
- More responsive
- More efficient