リファレンス
Reference

アニメーションで画像を切り替える

URLをコピーする Twitterでシェアする Facebookでシェアする

2 種類の要素をスムーズに切り替えて表示したい場合は、 AnimatedCrossFade を使うと便利です。

アニメーションの準備

まず、2 種類の要素を用意します

この例では、 image.network を使って、インターネット上から 2 種類の画像データを取得します。

そして、この画像を切り替えて表示するサンプルを作っていきます。

final firstImage = Image.network(
  'https://nzigen.com/flutter-reference/assets/img/samples/kit-jumper-0002.png',
  width: 300,
  height: 300,
);
final secondImage = Image.network(
  'https://nzigen.com/flutter-reference/assets/img/samples/kit-jumper-0003.png',
  width: 300,
  height: 300,
);

できるだけ、2 つの要素を同じサイズで用意しましょう。サイズが固定サイズでないと、表示する時に一緒にアニメーションしてしまうことがあります。 Flutter公式ドキュメントにも、「この Widget は同じサイズを持った要素で使われると想定されている」と書かれています。  違うサイズの要素を切り替えたい場合は、 SizedBox で囲むなどしてサイズを合わせると良いでしょう。

AnimatedCrossFade を構成する主な要素

AnimatedCrossFade を構成する主な要素は、以下のようになります。

AnimatedCrossFade(
  firstChild: firstImage,
  secondChild: secondImage,
  duration: Duration(seconds: 1),
  crossFadeState: crossFadeStateValue,
)

引数 firstChild に 1 枚目の画像、secondChild に 2 枚目の画像を渡します。

そして、 引数 duration には、 画像が切り替わる間隔時間を渡します。 Duration(seconds: 1) は 1 秒を意味します。

もし 0.5 秒 (500 ミリ秒) にしたいときは、 Duration(milliseconds: 500) とします。

crossFadeState には、表示されている要素を指定します。

firstChild に渡した要素を表示させたかったら、 CrossFadeState.showFirst を、

secondChild に渡した要素を表示させたかったら、 CrossFadeState.showSecond を指定します。

つまり、この crossFadeState に渡す値 crossFadeStateValue を切り替えることで、表示する要素を切り替えることができます。

ボタンを押すと、画像が切り替わるアニメーション実装例

以下のコード例では、「CHANGE」ボタンを押すごとに表示される画像が切り替わるアニメーションの実装例です。

全体のコードは以下のようになります。

class AnimatedCrossFadePage extends StatefulWidget {
  @override
  _AnimatedCrossFadePageState createState() => _AnimatedCrossFadePageState();
}

class _AnimatedCrossFadePageState extends State<AnimatedCrossFadePage> {
  bool showFirst = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            AnimatedCrossFade(
              firstChild: firstImage,
              secondChild: secondImage,
              duration: Duration(seconds: 1),
              crossFadeState:
              showFirst ? CrossFadeState.showFirst : CrossFadeState.showSecond,
            ),
            ElevatedButton(
              onPressed: () {
                setState(() {
                 showFirst = !showFirst;  // bool 値を切り替える
                });
              },
              child: Text('CHANGE'),
            ),
          ],
        ),
      ),
    );
  }
}

crossFadeState の状態に三項演算子を使うと、 bool 型一つで状態を管理できるのでとても便利です。

補足:三項演算子の箇所を if 構文にすると、以下のようになります。

if (showFirst == true) {
  crossFadeState: CrossFadeState.showFirst;
} else {
  crossFadeState: CrossFadeState.showSecond;
}

Timer を使って、時間差で自動的に画像が切り替わるアニメーション実装例

Timer を使い、設定する時間差で、 フェードイン・フェードアウトしながら、画像が切り替わるアニメーション実装例です。

全体のコードは以下のようになります。

class AnimatedCrossFadePage extends StatefulWidget {
  @override
  _AnimatedCrossFadePageState createState() => _AnimatedCrossFadePageState();
}

class _AnimatedCrossFadePageState extends State<AnimatedCrossFadePage> {
  CrossFadeState crossFadeStateValue = CrossFadeState.showFirst;
  late Timer crossFadeTimer;

  @override
  Widget build(BuildContext context) {
    final firstImage = Image.network(
      'https://nzigen.com/flutter-reference/assets/img/samples/kit-jumper-0002.png',
      width: 300,
      height: 300,
    );
    final secondImage = Image.network(
      'https://nzigen.com/flutter-reference/assets/img/samples/kit-jumper-0003.png',
      width: 300,
      height: 300,
    );
    return Scaffold(
      body: Center(
        child: AnimatedCrossFade(
          firstChild: firstImage,
          secondChild: secondImage,
          duration: Duration(seconds: 1),
          crossFadeState: crossFadeStateValue,
        ),
      ),
    );
  }

  @override
  void dispose() {
    crossFadeTimer.cancel();
    super.dispose();
  }

  @override
  void initState() {
    crossFadeTimer = Timer.periodic(Duration(milliseconds: 1000), (timer) {
      setState(() {
        if (crossFadeStateValue == CrossFadeState.showFirst) {
          crossFadeStateValue = CrossFadeState.showSecond;
        } else {
          crossFadeStateValue = CrossFadeState.showFirst;
        }
      });
    });

    super.initState();
  }
}

dispose メソッドは、 AnimatedCrossFadePage Widget クラスが破棄されるときに呼ばれるものです。 そして、この関数内には、この Widget 内でオブジェクトを生成する時に使ったメモリを解放する指示を書きます。 ここでは、 Timer オブジェクト crossFadeTimer を作ったので、その Timer のメモリを開放する cancel メソッドを実行します。

参考リンク