Flutterで半透明のローディングダイアログを実装する
Flutterでは、読み込み中などの時に表示を出すインジケーターが標準で備わっています。
ですが、これだと基本的には読み込みが完了するまで、インジケーターだけが画面に表示されることになります。こんな感じ。
UI的にはもう一段階工夫できる余地があるかなと思います。
そこで、最近多いのが、インジケータは出しつつ、画面を半透明にして、読み込みが完了するまで画面のコンテンツを表示する方法です。
以下のような感じですね。
やり方は以下の通りです。
1.半透明の画面とCircularProgressIndicatorを、showGeneralDialogにセットする
2.上記で作ったダイアログを呼び出し、続けて非同期で行う操作を記載し、ダイアログを閉じる
3.エラーハンドリングでもダイアログを閉じる
1.半透明の画面とローディングアイコンを、ダイアログにセットする
使いまわせるように、共通のコンポーネントとして作成しましょう。
lib/common とかのフォルダに置いておいておくと良いと思います。
Future <void> showLoadingDialog({
required BuildContext context,
}) async {
showGeneralDialog(
context: context,
barrierDismissible: false,
transitionDuration: const Duration(milliseconds: 250),
barrierColor: Colors.black.withOpacity(0.5), // 画面マスクの透明度
pageBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation) {
return WillPopScope(
onWillPop: ()async=> false,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
Text(S.of(context)!.processing,style: regularWhite18,),
],
),
),
);
});
}
-barrierColor のプロパティにwithOpacityを追加することで、透明度を指定
-WillPopScope を追加すると、処理中に端末の戻るボタンを無効にできます。例えば、課金操作とか、ログイン操作などで、通信中にユーザーの操作を制限したい場合などに使えます。
2.上記で作ったダイアログを呼び出し、続けて非同期で行う操作を記載し、ダイアログを閉じる
例えば、ログインの場面を想定すると、
Future<void> _login(BuildContext context) async {
//ダイアログを呼び出す
await showLoadingDialog(context: context);
//ログイン処理を行う
await login();
//ダイアログを閉じる
Navigator.pop(context);
}
こんな感じで、非同期でダイアログとログイン操作を呼び出し、ログイン操作が終わったらダイアログが閉じるようにします。
3.エラーハンドリングでもダイアログを閉じる
Future<void> _login(BuildContext context) async {
try {
await showLoadingDialog(context: context);
await login();
Navigator.pop(context);
} catch (e) {
//ダイアログを閉じる(追加)
Navigator.pop(context);
}
try~catchの中にNavigator.popを実装しておき、もし、ログイン処理でエラーが発生した場合でも、ダイアログを閉じる処理を追加しておきます。これがないと、エラー発生時にローディングが回ったままになってしまいます(ここは意外と盲点)
というわけで、以上です。
PS)手前味噌ですが、上記のGIF動画は、私が作成した筋トレ習慣化アプリの画面です。
筋トレ好き、筋トレこれから頑張りたい人は、よかったら使ってみてください〜★
◆Ios
◆Android
Discussion