Question #343MediumWidgets & UI

What is the purpose of the AnimatedBuilder widget in Flutter?

#widget#animation#animatedbuilder

Answer

Overview

text
AnimatedBuilder
is a widget that rebuilds its subtree whenever an animation value changes. It is the recommended way to build custom animations efficiently in Flutter.


Basic Usage

dart
class SpinningWidget extends StatefulWidget {
  
  _SpinningWidgetState createState() => _SpinningWidgetState();
}

class _SpinningWidgetState extends State<SpinningWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    )..repeat();
  }

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Transform.rotate(
          angle: _controller.value * 2 * 3.14, // 0 to 2π
          child: child, // 'child' doesn't rebuild!
        );
      },
      child: Icon(Icons.refresh, size: 48), // Built once, passed into builder
    );
  }
}

Why AnimatedBuilder?

Without

text
AnimatedBuilder
, you'd need
text
addListener
+
text
setState
:

dart
// ❌ Without AnimatedBuilder — rebuilds entire widget
_controller.addListener(() {
  setState(() {}); // Forces complete rebuild
});
dart
// ✅ With AnimatedBuilder — only rebuilds what changed
AnimatedBuilder(
  animation: _controller,
  builder: (context, child) {
    return Transform.scale(
      scale: _controller.value,
      child: child,
    );
  },
  child: ExpensiveWidget(), // ✅ Only built once!
)

Animation with Tween

dart
late AnimationController _controller;
late Animation<double> _fadeAnimation;
late Animation<Offset> _slideAnimation;


void initState() {
  super.initState();
  _controller = AnimationController(vsync: this, duration: Duration(milliseconds: 600));
  _fadeAnimation = Tween<double>(begin: 0, end: 1).animate(_controller);
  _slideAnimation = Tween<Offset>(begin: Offset(0, 0.5), end: Offset.zero)
      .animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut));
  _controller.forward();
}


Widget build(BuildContext context) {
  return AnimatedBuilder(
    animation: _controller,
    builder: (context, child) {
      return FadeTransition(
        opacity: _fadeAnimation,
        child: SlideTransition(
          position: _slideAnimation,
          child: child,
        ),
      );
    },
    child: Text('Animated!', style: TextStyle(fontSize: 24)),
  );
}

AnimatedBuilder vs Transition Widgets

ApproachUse When
text
AnimatedBuilder
Custom animation logic, multiple transforms
text
FadeTransition
Simple fade
text
SlideTransition
Simple slide
text
RotationTransition
Simple rotation
text
ScaleTransition
Simple scale

Key Tip: Always pass the non-animated

text
child
to
text
AnimatedBuilder
— it only builds that child once, making animations efficient even in complex widget trees.