[Flutter][Tips][11] Hero Widgetを使った滑らかなアニメーションの実装方法

どうも、末岐碧衣です。

Flutterでゲームアプリ開発してます。ボードゲームっぽいの作ってるんですが、マスに止まった時にモーダルでカードを表示したいなと。で、Flutterではどうやってやるねんってのを調べてみました。

 

Hero Widgetとは?

こういうアニメーションしたい時に使います。

Heroとは、皆さんご存知のあのヒーローのことです。スーパーマンとかアイアンマンとかアンパンマンとか。

Flutterでは、画面間を飛ぶウィジェットを指します。

要は、ヒーローをある画面から別の画面に飛ばすってことですね。例えば、ヒーローの形状を、円形から長方形に変形しながら、ある画面から別の画面へと飛行するアニメーションを作ることもできます。

 

Flutterのヒーローウィジェットは、共有要素の遷移または共有要素のアニメーションとして一般的に知られているアニメーションのスタイルを実装しています。

 

Heroに使われているTweenクラスとは?

HeroはTweenクラスを応用して作られてます。

Tweenってのは、開始値と終了値の間の線形補間を行うクラスです。

イメージは、紙芝居(パラパラ漫画)をアニメにしてくれるツール、かな。

1枚目と2枚目の間に起きている(と想定される)動きを、計算して絵を足して補間してくれるわけです。超高速&超大量のページを差し込んで補間することで、人間の目にはまるで滑らかに動いてるように見えるようにしてくれるのです。

まぁ別にこの辺は概念の話なので、Hero使いたいだけならそこまでちゃんと理解せずとも良さそう。

 

Heroアニメーション実装のポイント

ヒーローアニメーションは、開始(ソースルート)と終了(宛先ルート)の2つのHero Widgetを使って実装します。

開始と終了でそれぞれサイズや位置を定義しておけば、あとはTweenが勝手にその間の動き(アニメーション)を補間してくれるというわけですね!

まずはHeroクラスを作ります。

lib/hero.dart

class PhotoHero extends StatelessWidget {
  //Heroのアニメーションがホームプロパティにあるので、開始のHero Wedgetは暗黙的にpushされる
  const PhotoHero({ Key key, this.photo, this.onTap, this.width }) : super(key: key);

  final String photo;
  final VoidCallback onTap; 
  final double width;

  Widget build(BuildContext context) {
    return SizedBox(
      width: width,
      child: Hero(
        tag: photo,
        child: Material(
          color: Colors.transparent,
          child: InkWell(
            onTap: onTap,
            child: Image.asset(
              photo,
              fit: BoxFit.contain,
            ),
          ),
        ),
      ),
    );
  }
}

 

で、上記をメインソースで呼び出します。

lib/main.dart

...
    child: PhotoHero(
    photo: 'images/baseline_style_black_18dp.png',
    width: 30.0,
    onTap: () {
      Navigator.of(context).push(MaterialPageRoute<void>(
          builder: (BuildContext context) {
            return Scaffold(
                appBar: AppBar(
                  title: const Text('BlackCard Page'),
                ),
                body: Container(
                    color: Colors.lightBlueAccent,
                    padding: const EdgeInsets.all(16.0),
                    alignment: Alignment.topLeft,
                    child: PhotoHero(
                        photo: 'images/baseline_style_black_18dp.png',
                        width: 300.0,
                        onTap: () {
                          Navigator.of(context).pop();
                        }
                    )
                )
            );
          }
      ));
    }
),
...

実行結果はこんな感じ。

ふむ、、、、

動いた。けど、アイコン(写真)を拡大したいわけじゃなく、モーダルでカードの内容を表示したいので、よく考えたらやりたいことと違いますね(爆)

まぁ勉強になりました、ということで。。。

 

編集後記

GCPのデータエンジニア(プロ資格)認定試験が終わってぼんやりしてたら結構時間たっちゃってました。あ、ちゃんと合格しました( ´▽`) 出題傾向とか暗記ポイントとか色々まとめてあるので、GCPの資格とか興味ある人は覗いてってくださいませね。

[2020年7月] Google Cloud Certified – Professional Data Engineer日本語版(プロ認定):合格報告&勉強方法まとめ

 

話がちょっと逸れましたが、Flutterをはじめ、プログラミングって年々開発者に優しくなってるというか、簡単になってきてるので、今は独学とか初心者の人でも参入しやすいです。だからこそ私もできてるんですけどね(笑)

ただ、参入しやすいってことは、やっぱ成長していかないとどんどん自分が陳腐化しちゃうってことなので、そういう側面を考えるとなかなかしんどいですね。SIer的なとこにいるエンジニアの単価が下がってる(というか、上がってない)のには、そういうのも関係してるのかも、なんて。

要は、生涯現役でいたかったら、勉強し続けるしかないってことですね。

少なくとも、自分が楽しいと思えることじゃないと勉強し続けるって難しい気がしますね。

 

んふふ、ひとり言でした。

それでは!

末岐 碧衣
  • 末岐 碧衣
  • フリーランス のシステムエンジニア。独立後、一度も営業せずに月収 96 万円を達成。1986年大阪生まれ。早稲田大学理工学部卒。システムエンジニア歴 12年。
    2009年、ITコンサルティング企業に入社。3年目でコミュ障が爆発し人間関係が崩壊。うつにより休職するも、復帰後はコミュ障の自覚を持ち、「チームプレイ」を徹底的に避け、会社組織内においても「一人でできる仕事」に専念。社内外から評価を得た。
    無理に「チームプレイ」するよりも「一人でできる仕事」に専念した方が自分も周囲も幸せにできることを確信し、2015年フリーランスとして独立。