🐕

【Flutter Widget of the Week #27】AnimatedBuilderを使ってみた

2022/11/24に公開

はじめに

Flutter Widget of the Week #27 AnimatedBuilder についてまとめましたので、紹介します。
https://youtu.be/N-RiyZlv8v8

AnimatedBuilder

Flutter には widget を簡単にアニメートするオプションをたくさん提供されています。
中でも今回紹介する AnimatedBuilder は使い方もシンプルで幅広く使えるので、実用性が高い widget です。
では、さっそくサンプルを動かして使い方を見てみましょう。

AnimatedBuilder サンプルコード

AnimatedBuilder サンプル実行画面
AnimatedBuilder サンプル実行画面

基本のサンプルコード全体

import 'dart:math' as math;

class AnimatedBuilderSample extends StatefulWidget {
  const AnimatedBuilderSample({super.key});

  
  State<AnimatedBuilderSample> createState() => _AnimatedBuilderSampleState();
}

class _AnimatedBuilderSampleState extends State<AnimatedBuilderSample>
    with TickerProviderStateMixin {
  late final AnimationController _controller;

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

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

  
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      child: Container(
        width: 200.0,
        height: 200.0,
        color: Colors.green,
        child: const Center(
          child: Text('Whee!'),
        ),
      ),
      builder: (BuildContext context, Widget? child) {
        return Transform.rotate(
          angle: _controller.value * 2.0 * math.pi,
          child: child,
        );
      },
    );
  }
}

使い方としては、
まず AnimationController でライフサイクルを管理するためにStatefulWidgetを用意します。
Controller に vsync を提供するためには、StatefulWidget に TickerProviderMixin を適用する必要があります。

class _AnimatedBuilderSampleState extends State<AnimatedBuilderSample>
    with TickerProviderStateMixin {}

次にアニメーションを与えるためのインスタンスを作成します。
ここでは10秒間のアニメーションを繰り返す設定をしています。
作成したインスタンスは widget の状態を通して管理するため、initState で作るようにすると良いでしょう。

late final AnimationController _controller = AnimationController(
  duration: const Duration(seconds: 10),
  vsync: this,
)..repeat();

そして builder を与えてアニメートする widget に返します。
ここでは回転トランスフォームを用いてスピン効果を作成しています。

return AnimatedBuilder(
  animation: _controller,
  child: Container(
    width: 200.0,
    height: 200.0,
    color: Colors.green,
    child: const Center(
      child: Text('Whee!'),
    ),
  ),
  // builder 部分 ここから
  builder: (BuildContext context, Widget? child) {
    return Transform.rotate(
      angle: _controller.value * 2.0 * math.pi,
      child: child,
    );
  },
  // ここまで
);

AnimatedBuilder にそのアニメーションから独立した任意の子を与えることもできます。
上のコードで言うと、builder 内の child に AnimatedBuilder の child で指定した Container を与えていて、そのレンダリングも AnimatedBuilder が最適化してくれています。

AnimatedBuilder のプロパティについて

AnimatedBuilder には基本的なプロパティしかなく、
細かな設定は animation や builder のなかで行っています。

(new) AnimatedBuilder AnimatedBuilder({
  Key? key,
  required Listenable animation,
  required Widget Function(BuildContext, Widget?) builder,
  Widget? child,
})

①animation

与えられた Listenable がその通知をトリガーするたびに、ビルダーコールバックを使用して widget を再構築する設定をする
型は double 型

②builder

アニメーションの値が変化するたびに呼び出される関数を指定する
型は Function(BuildContext, Widget?) 型

最後に

今回は AnimatedBuilder を紹介しました。これまでもアニメーションを実現するための widget をいくつか紹介したと思いますが、今回のは使い方も汎用性もあるので、是非使って効果を実感してみてください。
次は #28 Dismissible です。またお会いしましょう。

参考記事

https://api.flutter.dev/flutter/widgets/AnimatedBuilder-class.html

Discussion