[Flutter/Dart] showDialogのダイアログを領域外タップやバックキーで閉じないようにする

2020年11月25日

showDialogのダイアログを領域外タップやバックキーで閉じないようにする

Flutter において showDialog によって表示されるダイアログ(モーダル)は、デフォルトではそのダイアログの背景をタップしたり、Android であればバックキー(戻るボタン)をタップしたりすることで閉じることができます。

この際 showDialog は戻り値として null を返します。場合によってはこれが好ましい挙動ではなく、ダイアログ内のボタンによってのみ閉じられるようにしたい、しっかり bool の値(Future)を返してほしい、などということがあるかも知れません。

iOSの場合

iOSにはバックキーがないので、ダイアログの背景(バリア)をタップした際にダイアログが閉じることを防げばOKです。

ダイアログの領域外のバリアをタップした際に閉じないようにするには showDialog のプロパティである barrierDismissible を false に設定します。

Future<bool> myShowDialog(BuildContext parent) {
  return showDialog(
    barrierDismissible: false,
    context: parent,
    builder: (BuildContext context) {
      return AlertDialog(
            title: Text('タイトル'),
            content: Text('ダイアログ本文'),
            actions: [
              TextButton(
                  child: Text('CANCEL'),
                  onPressed: () => Navigator.of(context).pop(false),
              ),
              TextButton(
                  child: Text('OK'),
                  onPressed: () => Navigator.of(context).pop(true)
              ),
            ],
          );
    },
  );
}

Androidの場合

Android にはバックキーがあるので、これによって閉じられることを防ぐ必要があります。

これには WillPopScope を使用し、その子要素としてダイアログ(以下の例ではAlertDialog)を持たせます。WillPopScope の onWillPop において false を返せば、バックキーによるダイアログの非表示化を防ぐことができます。

また、この処理を行った際はバリアのタップによってもダイアログが閉じなくなるため barrierDismissible の指定は不要になります。

Future<bool> myShowDialog(BuildContext parent) {
  return showDialog(
    // barrierDismissible: false, 自動的に閉じられなくなるため不要
    context: parent,
    builder: (BuildContext context) {
      return WillPopScope(
          onWillPop: () async => false,
          child: AlertDialog(
            title: Text('タイトル'),
            content: Text('ダイアログ本文'),
            actions: [
              TextButton(
                  child: Text('CANCEL'),
                  onPressed: () => Navigator.of(context).pop(false),
              ),
              TextButton(
                  child: Text('OK'),
                  onPressed: () => Navigator.of(context).pop(true)),
            ],
          ));
    },
  );
}

以上、ダイアログを領域外タップやバックキーで閉じないようにする方法についてでした。

参考

barrierDismissible property - ModalRoute class - widgets library - Dart API

WillPopScope class - widgets library - Dart API

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です