ボタン押下時にフェードインさせる情報はいくつか見つかったものの、初期表示時の情報は見つけられなかったのでメモ。
実現したいこと
画面の初期表示時に特定のウィジェットをフェードインで表示させたい。
AnimationControllerは使わず簡単に実装したい。
実現方法
フェードインさせたいウィジェットをAnimatedOpacityでラップし、画面ビルド後にopacity値(不透明度)を0から1に変化させる。
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
/// opacityの変化を監視できるようにするためのStateProvider
final opacityProvider = StateProvider.autoDispose<double>((ref) {
// opacityの初期値
return 0;
});
/// フェードインウィジェットがあるページ
class SamplePage extends ConsumerWidget {
const SamplePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// 不透明度の変化を監視
final opacity = ref.watch(opacityProvider);
WidgetsBinding.instance.addPostFrameCallback(
(timeStamp) async {
// ビルド後に実行されるコールバック関数
// 監視中のopacityを1に更新
ref.read(opacityProvider.notifier).state = 1;
},
);
return Scaffold(
appBar: AppBar(
title: const Text('AnimatedOpacity Demo'),
centerTitle: true,
),
body: AnimatedOpacity(
// 不透明度
opacity: opacity,
// フェードイン完了までの間隔
duration: const Duration(seconds: 1),
// フェードインさせるウィジェット
child: Center(
child: Container(
color: Colors.blue,
height: 300,
width: 300,
),
),
),
);
}
}
/// 遷移ボタンのページ
class SamplePage2 extends StatelessWidget {
const SamplePage2({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: OutlinedButton(
onPressed: () => Navigator.of(context).push(
// フェードイン以外のアニメーションがあるとわかりにくいのでオフ
PageRouteBuilder(
pageBuilder: (_, __, ___) => const SamplePage(),
transitionDuration: const Duration(seconds: 0),
),
),
child: const Text('フェードインページに遷移します'),
),
),
);
}
}
なぜビルド後に変化させなければならないか?
AnimatedOpacityが、opacityの値が変化したときにアニメーションで切り替わるウィジェットだから。
Animated version of Opacity which automatically transitions the child's opacity over a given duration whenever the given opacity changes.
Google翻訳:指定された不透明度が変化するたびに、指定された期間にわたって子の不透明度を自動的に遷移させる Opacity のアニメーション バージョン。
フェードインさせたい場合は、一度 opacity: 0 → 1 の変化を経ないといけないわけですね。