Flutter: SnackBarが非表示になったタイミングで実行される処理の実装方法
はじめに
リスト内の要素をスワイプして削除できるようにする機能を個人開発で実装する場面があった。
スワイプ後にSnackBar
でアクションの内容を通知し、それが表示されている間はアクションを取り消すことができてSnackBar
が非表示になったタイミングでアクションの実行を完了させる、というものだ。
イメージとしては以下。
SnackBar
は今までも処理結果の通知などでよく利用していたが、それが非表示になったタイミングで特定の処理を走らせるということは今まで実装したことがなかったので残しておく。
対応方法
SnackBar
の表示にはScaffoldMessenger.of(context).showSnackBar(snackBar)
を利用するが、このshowSnackBar
メソッドはScaffoldFeatureController<SnackBar, SnackBarClosedReason>
という返り値を持っている。
ScaffoldFeatureController
のclosed
というプロパティを使うことで、SnackBarClosedReason
というSnackBar
がどうやって閉じられたかの情報を取得することができる。これを利用して閉じられた場面ごとに処理を出し分けることが可能になる。SnackBarClosedReason
はenum
であり、利用できる値は以下。
enum SnackBarClosedReason {
// SnackBarActionによって閉じられたとき
action,
// SemanticsAction.dismissによって閉じられたとき
dismiss,
// ユーザーがSnackBarをスワイプして閉じたとき
swipe,
// ScaffoldFeatureControllerのcloseコールバック、または、ScaffoldMessengerState.hideCurrentSnackBarを直接実行したとき
hide,
// ScaffoldMessengerState.removeCurrentSnackBarによって閉じられたとき
remove,
// 設定していたタイマーの時間が過ぎたとき
timeout,
}
以下の実装例では、SnackBarAction
以外でSnackBar
が閉じられた際に処理を走らせている。
TextButton(
onPressed: () async {
// SnackBarの生成
final snackBar = SnackBar(
action: SnackBarAction(
label: '元に戻す',
onPressed: () {/* 処理 */},
),
content: const Text('アーカイブしました'),
);
// SnackBarを表示し、閉じられた理由を取得する
final controller = ScaffoldMessenger.of(context).showSnackBar(snackBar);
final closedReason = await controller.closed;
// SnackBarがアクションで閉じられた場合は処理を実行せず、それ以外の場合に処理を実行する
if (closedReason != SnackBarClosedReason.action) {
// SnackBarが非表示になったときの処理
}
},
child: Text('ボタン'),
),
おわり
これでSnackBar
が非表示になった際に処理を走らせることができるようになった。良きSnackBar
ライフを!