Flutter - Using AnimatedBuilder Widget Examples

This tutorial shows you how to create animation using AnimatedWidget in Flutter.

Flutter has a class named AnimatedWidget. It's a widget that rebuilds each time its Listenable changes value. That behavior makes it possible for us to create a custom animation by creating a class that extends AnimatedWidget and providing the Listenable.

Using AnimatedWidget

First, we need to create a class that extends AnimatedWidget and override the build method. The widget's constructor needs to call its superclass' constructor which is shown below.

  const AnimatedWidget({
    Key key,
    @required this.listenable,
  })

That means it's required to pass a listenable argument whose type is Listenable. How to get the value that can be passed as listenable will be explained later.

Assuming the listenable is already passed, we can access it within the class that extends AnimatedWidget. It can be any instance whose class extends Listenable. In this tutorial, we are going to use an AnimationController which is a common type to be passed as the Listenable.

AnimatedWidget performs rebuild when the value of its Listenable changes. In the following example, we want to get the value of the Animation to apply rotation transformation. The current animation value is used to determine the rotation angle. At each animation tick, the animation value changes and therefore the rotation angle also changes.

  class RotatingSquare extends AnimatedWidget {
  
    const RotatingSquare({Key? key, required AnimationController controller})
        : super(key: key, listenable: controller);
  
    Animation<double> get _progress => listenable as Animation<double>;
  
    @override
    Widget build(BuildContext context) {
      return Transform.rotate(
        angle: _progress.value * 2.0 * math.pi,
        child: Container(
          width: 200.0,
          height: 200.0,
          color: Colors.teal,
          child: const Center(
            child: Text(
              'Woolha.com',
              style: TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                fontSize: 24,
              ),
            ),
          ),
        ),
      );
    }

In order to create the create an instance of RotatingSquare class above, we have to pass an AnimationController. We need to create a class that extends State and use TickerProviderStateMixin. That makes it possible to use this keyword to be passed as vsync when calling the constructor of AnimationController. The animation needs to be started, such as by using forward(), reverse(), or repeat(). Having created the AnimationController, now it becomes possible to call the constructor of _RotationgSquare.

  class _AnimatedWidgetExample extends StatefulWidget {
    @override
    State<StatefulWidget> createState() =>
      new _AnimatedWidgetExampleState();
  }
  
  class _AnimatedWidgetExampleState extends State<_AnimatedWidgetExample> with TickerProviderStateMixin {
  
    late AnimationController _controller;
  
    void initState() {
      super.initState();
      _controller = AnimationController(
        duration: const Duration(seconds: 5),
        vsync: this,
      )..repeat();
    }
  
    @override
    void dispose() {
      _controller.dispose();
      super.dispose();
    }
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Woolha.com Flutter Tutorial'),
        ),
        body: Center(
          child: RotatingSquare(controller: _controller),
        ),
      );
    }
  }

Output:

Flutter - AnimatedWidget

 

Full Code

Here's the full code of this tutorial.

  import 'dart:math' as math;
  import 'package:flutter/material.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: _AnimatedWidgetExample(),
      );
    }
  }
  
  class _AnimatedWidgetExample extends StatefulWidget {
    @override
    State<StatefulWidget> createState() =>
      new _AnimatedWidgetExampleState();
  }
  
  class _AnimatedWidgetExampleState extends State<_AnimatedWidgetExample> with TickerProviderStateMixin {
  
    late AnimationController _controller;
  
    void initState() {
      super.initState();
      _controller = AnimationController(
        duration: const Duration(seconds: 5),
        vsync: this,
      )..repeat();
    }
  
    @override
    void dispose() {
      _controller.dispose();
      super.dispose();
    }
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Woolha.com Flutter Tutorial'),
        ),
        body: Center(
          child: RotatingSquare(controller: _controller),
        ),
      );
    }
  }
  
  class RotatingSquare extends AnimatedWidget {
  
    const RotatingSquare({Key? key, required AnimationController controller})
        : super(key: key, listenable: controller);
  
    Animation<double> get _progress => listenable as Animation<double>;
  
    @override
    Widget build(BuildContext context) {
      return Transform.rotate(
        angle: _progress.value * 2.0 * math.pi,
        child: Container(
          width: 200.0,
          height: 200.0,
          color: Colors.teal,
          child: const Center(
            child: Text(
              'Woolha.com',
              style: TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                fontSize: 24,
              ),
            ),
          ),
        ),
      );
    }
  }

Another way to create animation is using AnimatedBuilder. Unlike AnimatedWidget that requires us to create a class for the widget to be animated, AnimatedBuilder can be used to create an animation as a part of a larger build function.