Animated Bar Chart with Flutter Hooks

In this blog post, we described how to use animations to animate a bar chart. In this blog post were are going to add another possible way to animate the bar chart. We are going to use Flutter Hooks to extract the disposing and setup of the animation controller into the hook. This means we do not have to do this for each animation we want to create in our application.

Configuring the project

Before we can start with coding, we are going to add a dependency to the project, namely Flutter Hooks. For this we have to update our pubspec.yaml with the following dependency:

dependencies:
  flutter_hooks: ^0.14.1

Do not forget to install the dependency, running the following command:

flutter pub get

That is it! We can now use Flutter Hooks in the project.

Using the HookWidget

Let’s take a quick look at the previous animation before we start:

class _BarChartState extends State with SingleTickerProviderStateMixin {
  Map data = {
    "Banana": 16,
    "Orange": 8,
    "Appple": 10,
    "Kiwi": 10,
    "Pear": 3,
  };
  Animation animation;
  AnimationController controller;
  @override
  void initState() {
    super.initState();
    controller = AnimationController(duration: const Duration(seconds: 2));
    animation = Tween(begin: 0, end: 100).animate(controller)
      ..addListener(() {
        setState(() {});
      });
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: BarChartPainter(data, "Favorite Fruit", animation.value),
      child: Container(
        width: 350,
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

Here we have to manage the controller and the animation. We have to add logic to the initState and to the dispose methods, to set up and clean up the animation and controller. So how would we do this with a hook:

class BarChart extends HookWidget {
  final Duration duration = const Duration(seconds: 2);

  @override
  Widget build(BuildContext context) {
    final controller = useAnimationController(duration: duration);
    controller.forward();
    return BarChartContainer(controller: controller);
  }
}

class BarChartContainer extends AnimatedWidget {
  BarChartContainer({AnimationController controller})
      : super(
            listenable: Tween(begin: 0, end: 100).animate(controller));

  static const Map data = {
    "Banana": 16,
    "Orange": 8,
    "Appple": 10,
    "Kiwi": 10,
    "Pear": 3,
  };

  @override
  Widget build(BuildContext context) {
    Animation animation = listenable;
    return CustomPaint(
      painter: BarChartPainter(data, "Favorite Fruit", animation.value),
      child: Container(
        width: 350,
      ),
    );
  }
}

Here we extended the BarChart with an HookWidget. This allows us to use hooks. The hooks were are using is:

    final controller = useAnimationController(duration: duration);
    controller.forward();

The logic of disposing and setting up the controller is done in the useAnimationController Hook. We had to wrap the BarChartPainter in a BarChartContainer. The reason for this is that the BarChartPainter already extends the CustomPainter and the Widget that gets passed the AnimationController should extend the AnimatedWidget. That was all we had to do, to update a default animation to animation with a hook. Thanks for reading, you can find the code here!

Leave a Reply