Flutter Animations: Part 4

In the first three parts of this series on Animations in Flutter we have covered Implicit Animations and Transition Animations. Those two approaches to creating Animations will cover most typical use cases. In this article, we’d like to cover a Widget that provides a more advanced way to animate with Flutter: The AnimatedBuilder Widget.
AnimatedBuilder Widget
The AnimatedBuilder Widget is useful for more complex Widgets that wish to include an animation as part of a larger build function. To construct an AnimatedBuilder Widget, we start off much the same way as the Transition Animations we covered in the previous article. We need a Stateful and State Widget that makes use of an Animation and AnimationController, much like the State Widget we created in the previous article.
Here’s an example implementation:
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: const Duration(seconds: 5),
vsync: this,
)..addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
} else if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
_animation = Tween<double>(begin: 0, end: 400).animate(_controller);
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.rotate(
angle: _controller.value,
child: Container(
width: _controller.value * 2,
height: _controller.value * 2,
color: Colors.blue,
),
);
},
);
}
}
In this example, we’re animating a double
value from 0 to 400 over a period of 5 seconds. The cascade notation (..
) allows us to call multiple methods on the same object. We use ..addStatusListener
to listen to the status of the Animation.
When the Animation is completed, we reverse the animation. When it’s dismissed (after the reverse completes), we start it forward again, creating a continuous animation loop.
How AnimatedBuilder Works
The AnimatedBuilder Widget rebuilds the portion of the Widget tree defined in its builder method each time the animation value changes. In our example, we use the animation value to:
- Calculate the angle of rotation for the child widget using
Transform.rotate
- Set the width and height of the Container Widget based on the controller value
This gives us fine-grained control over how the animation affects our widget tree, without having to manually call setState()
or rebuild the entire widget.
When to Use AnimatedBuilder
While most of your animation needs can be met with Implicit and Transition Animations, AnimatedBuilder is particularly useful when you need:
- More complex animation logic integrated into a larger widget
- Multiple properties animating simultaneously with custom calculations
- Animations that affect multiple child widgets in different ways
- Fine-grained control over the rebuild process during animations
In the next part of this series, we’ll explore easing curves in Flutter animations to create more natural-feeling motion.