リバース・エンジニアリング

Flultterとテックブログと時々iOS

56.【ナンバーズアプリ】Flutter のアニメーション AnimationController の基礎を振り返る

目次

今回は Flutter のアニメーションについて書いてますが学習途中なので所々間違いがあるかもしれませんのでご了承ください。

Flutter でアニメーションを実装できる AnimationController を説明してみる

前回は円を描写しましたがアニメーションがまだできていません。

blog.tamappe.com

Flutterでのアニメーションの入れ方を調査しなければならなかったので、本日は Flutter のアニメションについて学習します。

AnimationController とは

Animation については Flutter 公式ページの方が理解が進みます。

flutter.dev

今回はその一番の基礎である AnimationController について説明してみます。

一番分かりやすい動画はこちらになります。

youtu.be

AnimationController の基礎

AnimationController の基礎は次の2つで構成されます。

  • mixin の適用
  • AnimationController を宣言する

それぞれ順を追って説明します。

mixin の適用

mixin のイメージは iOS で言えば、delegate に近いです。

Animation は状態が変わるので基本は StatefulWidget を使って

class AnimationWidgetState extends StatefulWidget {
  @override
  _AnimationWidgetStateState createState() => _AnimationWidgetStateState();
}

class _AnimationWidgetStateState extends State<AnimationWidgetState> with SingleTickerProviderStateMixin {

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

SingleTickerProviderStateMixin を mixin させます。

これで AnimationController を使う準備ができました。

AnimationController を宣言する

それではさきほど作成した AnimationWidgetStateに AnimationController を宣言します。
AnimationController はライフサイクルを持っているので initStatedispose で生成や廃棄をしないといけないみたいな感じです。

class AnimationWidgetState extends StatefulWidget {
  @override
  _AnimationWidgetStateState createState() => _AnimationWidgetStateState();
}

class _AnimationWidgetStateState extends State<AnimationWidgetState>
    with SingleTickerProviderStateMixin {
  /// 宣言する
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    /// 初期化する
    _controller = AnimationController(
        vsync: this, 
        duration: Duration(seconds: 60)
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  void dispose() {
    super.dispose();
    /// 廃棄する
    _controller.dispose();
  }
}

これが AnimationController を使う場合の基本形になります。
慣れない時はこれを3回書いて暗記してしまいましょう。

initState メソッドを見てみます。

    _controller = AnimationController(
        vsync: this, 
        duration: Duration(seconds: 60)
    );

ここですね。 duration はお馴染みのアニメーション時間ですが、 vsync (ビィーシンクと発音するみたいです)は初見ですね。
vsync は今はまだ分かりませんが慣例としてthisをセットすればいいみたいです。
duration が割とハマったりします。

/// マイクロ秒
Duration(microseconds: 60)

/// ミリ秒
Duration(milliseconds: 60)

/// 秒
Duration(seconds: 60)

/// 分
Duration(minutes: 60)

こんな感じです。

f:id:qed805:20200516180020p:plain:w300
Duration のプロパティ

これらを宣言し終わったら Animation の基礎は完成します。
XML とかクロージャーなどを使うと思っていましたので簡単そうに見えますね。

Listener を追加する

AnimationController で基礎が出来上がったら Listener を追加していきます。

initState の中で addListener します。

  @override
  void initState() {
    super.initState();
    /// 初期化する
    _controller = AnimationController(
        vsync: this,
        duration: Duration(seconds: 60)
    );
    _controller.addListener(_update);
  }

  void _update() {
    setState(() {
    });
  }

あとは _update() の中で行いたい処理を書いていきます。

forward() でアニメーションを開始させる

上記でアニメーション用の処理を書きました。
それでは実際にアニメーションを開始させたいです。

アニメーションを開始したい場合は簡単に Listener を追加した後に

    _controller.forward();

という風に forward() を実行するだけでOKです。
つまり、Widget 表示時にアニメーションを開始したい場合は initState のところで

  @override
  void initState() {
    super.initState();
    /// 初期化する
    _controller = AnimationController(
        vsync: this,
        duration: Duration(seconds: 60)
    );
    _controller.addListener(_update);
    _controller.forward();
  }

とすれば表示と同時にアニメーションが始まります。

紹介した動画の中では int 型の i を宣言して i の値を更新していっていました。

動画の中で紹介されていたコード

class AnimationWidgetState extends StatefulWidget {
  @override
  _AnimationWidgetStateState createState() => _AnimationWidgetStateState();
}

class _AnimationWidgetStateState extends State<AnimationWidgetState>
    with SingleTickerProviderStateMixin {
  /// 宣言する
  AnimationController _controller;

  int i = 0;

  @override
  void initState() {
    super.initState();
    /// 初期化する
    _controller = AnimationController(
        vsync: this,
        duration: Duration(seconds: 60)
    );
    _controller.addListener(_update);
    _controller.forward();
  }

  void _update() {
    setState(() {
      i = (_controller.value * 2993030303).round();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text('$i m/s');
  }

  @override
  void dispose() {
    super.dispose();
    /// 廃棄する
    _controller.dispose();
  }
}

これを実行すると i の値が高速で変更されていく画面が表示されます。

ちなみに AnimationController の duration は別に設定しなくても動作したりしました。

    _controller = AnimationController(
        vsync: this,
    );

これだけで行けるみたいです。
繰り返し処理したい場合には

    _controller = AnimationController(
        vsync: this,
    )..repeat();

このように ..repeat と書けばアニメーションがリピートされます。

これらが分かればとりあえずは Flutter での簡単なアニメーションが実現できるようになりますね。 使ってみれば以外に簡単な気がしますのでこれからはできるだけアニメーションを使っていきたいと思います。

それではバイバイ。