在Flutter中防止对话框在外部触摸时关闭

117
在Flutter中,我为异步任务编写了一个简单的对话框以显示加载器。当我点击对话框外部时会自动关闭,如何停止这种行为?

代码

  showDialog(
    context: context,
    builder: (_) => new Dialog(
          child: new Container(
            alignment: FractionalOffset.center,
            height: 80.0,
            padding: const EdgeInsets.all(20.0),
            child: new Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                new CircularProgressIndicator(),
                new Padding(
                  padding: new EdgeInsets.only(left: 10.0),
                  child: new Text("Loading"),
                ),
              ],
            ),
          ),
        ));

2
此内容已有答案,请参考 https://dev59.com/_VUL5IYBdhLWcg3wOl9x#50635504。 - Vinoth Kumar
8个回答

302

有一个名为barrierDismissible的属性,你可以传递给showDialog方法;它可以控制点击非对话框区域是否可以关闭对话框。

showDialog(
  barrierDismissible: false,
  builder: ...
)

3
如何处理 barrierDismissible,比如当在外部点击时添加不同的活动。 - user11065582
13
在Android中,您仍可以通过按“返回”按钮来关闭对话框。是否有一种方法也可以防止这种情况发生呢? - Alex Semeniuk
8
你可以使用WillPopScope将对话框构建器小部件包围起来。参考这个答案:https://dev59.com/DVcO5IYBdhLWcg3wXwh3 - Dpedrinha
如果您正在使用 showModalBottomSheet,那么您需要将 isDismissible: false 设为 true。 - Maruf Hassan
showCupertinoDialog也有这个属性。 - Pranav Kasetti

56

如果您想要防止对话框在按下后退按钮时关闭,则请参考以下代码。您需要在WillPopScope小部件中包装您的AlertDialog,并使onWillPop属性值为返回Future.value(false)的函数。

showDialog(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext context) {
        return WillPopScope(
            onWillPop: () => Future.value(false),
            child:AlertDialog(
            title: new Text("Alert Title"),
            content: new SingleChildScrollView(
              child: Container(),),
            actions: <Widget>[
              new FlatButton(
                child: new Text("Close"),
                onPressed: () {
                },
              ),
            ],
          )
        )
      },
    );

7
现在不可能使用 onWillPop: (){}。正确的变体是 onWillPop: () => Future.value(false) - Valentina Konyukhova
1
或者 onWillPop: () async => false, - Defuera
@ValentinaKonyukhova 是的,你说得对。我已经更新了我的答案。谢谢。 - Sachin Tanpure
感谢这个解决方案,可以防止所有的解雇方法。 - wanz

19

只需添加这一行

barrierDismissible: false,

就像

       showDialog(
        barrierDismissible: false,
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text(
              "Classes",
              style: TextStyle(
                  fontSize: 24, color: Colors.black, fontFamily: 'intel'),
            ),
            content: setupAlertDialoadClassList(
                context, listClasses, Icons.class__outlined, 0),
          );
        });

7

barrierDismissible: false,

使用以下方式进行配置。 showDialog( barrierDismissible: false, builder // 代码 //


5

这将禁用设备导航

showDialog(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext context) {
        return WillPopScope(
            onWillPop: () async => false,
            child:AlertDialog(
            title: new Text("Alert Title"),
            content: new SingleChildScrollView(
              child: Container(),),
            actions: <Widget>[
              new FlatButton(
                child: new Text("Close"),
                onPressed: () {
                },
              ),
            ],
          )
        )
      },
    );

正是我所需要的,因为 barrierDismissible: false, 防止了通过在对话框外部点击来关闭它,但你仍然可以通过按返回按钮来关闭它。 - Ojonugwa Jude Ochalifu

2

始终使用顶级的Flutter软件包,例如get

Get.generalDialog(pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation,) {
      return SimpleDialog(
        ...
      );
    }, barrierDismissible: false /* its default value */);

谢谢。这就是我需要的getX包。 - ANDYNVT
1
糟糕的建议。你绝对不需要使用GetX。而且,总体上最好避免使用GetX。 - Muhammad Vaid

1
手机导航栏操作禁用并在AlertDialog中禁用外部触摸。
showDialog(
  context: context,
  barrierDismissible: false,    // <-- Set this to false.
  builder: (_) => WillPopScope(
    onWillPop: () async => false, // <-- Prevents dialog dismiss on press of back button.
    child: AlertDialog(),
  ),
);

0

如果您没有使用showDialog,否则您正在使用GestureDetector,我刚刚找到了一种简单的方法。只需在另一个GestureDetector中放置一个GestureDetector,然后在两个GestureDetector上设置onTap操作(如果这是您的情况),其中一个差异是您将在其中一个操作中放置一个动作,而在另一个操作中可以将其留空,就像这样。

GestureDetector(
    onTap: () { //The Gesture you dont want to afect the rest
      Navigator.pop(context);
    },
    child: Container(
      color: Colors.transparent,
      child:GestureDetector(
            onTap: () {}, //This way is not going to afect the inside widget
            child: Container() //your widget
            )
          )
        )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接