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
メソッドを実行します。