【问题标题】:How to make an AlertDialog in Flutter?如何在 Flutter 中制作 AlertDialog?
【发布时间】:2019-05-19 12:31:13
【问题描述】:

我正在学习在 Flutter 中构建应用程序。现在我来警告对话框了。我之前在AndroidiOS 中做过,但是如何在 Flutter 中发出警报?

以下是一些相关的 SO 问题:

我想做一个更一般的规范问答,所以我的答案如下。

【问题讨论】:

标签: dart flutter flutter-alertdialog


【解决方案1】:

一个按钮

showAlertDialog(BuildContext context) {

  // set up the button
  Widget okButton = TextButton(
    child: Text("OK"),
    onPressed: () { },
  );

  // set up the AlertDialog
  AlertDialog alert = AlertDialog(
    title: Text("My title"),
    content: Text("This is my message."),
    actions: [
      okButton,
    ],
  );

  // show the dialog
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return alert;
    },
  );
}

两个按钮

showAlertDialog(BuildContext context) {

  // set up the buttons
  Widget cancelButton = TextButton(
    child: Text("Cancel"),
    onPressed:  () {},
  );
  Widget continueButton = TextButton(
    child: Text("Continue"),
    onPressed:  () {},
  );

  // set up the AlertDialog
  AlertDialog alert = AlertDialog(
    title: Text("AlertDialog"),
    content: Text("Would you like to continue learning how to use Flutter alerts?"),
    actions: [
      cancelButton,
      continueButton,
    ],
  );

  // show the dialog
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return alert;
    },
  );
}

三个按钮

showAlertDialog(BuildContext context) {

  // set up the buttons
  Widget remindButton = TextButton(
    child: Text("Remind me later"),
    onPressed:  () {},
  );
  Widget cancelButton = TextButton(
    child: Text("Cancel"),
    onPressed:  () {},
  );
  Widget launchButton = TextButton(
    child: Text("Launch missile"),
    onPressed:  () {},
  );

  // set up the AlertDialog
  AlertDialog alert = AlertDialog(
    title: Text("Notice"),
    content: Text("Launching this missile will destroy the entire universe. Is this what you intended to do?"),
    actions: [
      remindButton,
      cancelButton,
      launchButton,
    ],
  );

  // show the dialog
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return alert;
    },
  );
}

处理按钮按下

以上示例中按钮的 onPressed 回调为空,但您可以添加如下内容:

Widget launchButton = TextButton(
  child: Text("Launch missile"),
  onPressed:  () {
    Navigator.of(context).pop(); // dismiss dialog
    launchMissile();
  },
);

如果你回调null,那么按钮将被禁用。

onPressed: null,

补充代码

这是main.dart 的代码,以防您无法运行上述函数。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter'),
        ),
        body: MyLayout()),
    );
  }
}

class MyLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: ElevatedButton(
        child: Text('Show alert'),
        onPressed: () {
          showAlertDialog(context);
        },
      ),
    );
  }
}

// replace this function with the examples above
showAlertDialog(BuildContext context) { ... }

【讨论】:

  • Navigator.of(context).pop();不会关闭对话框,而是关闭它下方的屏幕。对话仍然存在。
  • @GunJack,听起来您使用的设置与我在这里的设置不同。此处的示例中只有一个屏幕。
  • 是的,我想是因为我使用了多个导航器。直接在按钮的 onPressed 方法中调用 showDialog 有效。但是从 onPressed 调用 showAlertDialog 函数会导致奇怪的行为。
  • 很好的答案!此外,如果您想构建自己的自定义对话框,您可以使用Dialog 小部件来实现。它与上面的答案相同,但不是使用AlertDialog,这个类可以返回您构建的任何自定义小部件,因此它将显示为弹出窗口。阅读更多medium article
  • @Suragch 我错过了showDialog 是来自package:flutter/src/material/dialog.dart 的方法。我以为我必须进行条件渲染才能显示对话框。
【解决方案2】:

我使用了类似的方法,但我想

  1. 将对话框代码作为小部件保存在单独的文件中,以便我可以重复使用它
  2. 显示对话框时模糊背景。

代码: 1.alertDialog_widget.dart

import 'dart:ui';
import 'package:flutter/material.dart';


class BlurryDialog extends StatelessWidget {

  String title;
  String content;
  VoidCallback continueCallBack;

  BlurryDialog(this.title, this.content, this.continueCallBack);
  TextStyle textStyle = TextStyle (color: Colors.black);

  @override
  Widget build(BuildContext context) {
    return BackdropFilter(
      filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
      child:  AlertDialog(
      title: new Text(title,style: textStyle,),
      content: new Text(content, style: textStyle,),
      actions: <Widget>[
        new FlatButton(
          child: new Text("Continue"),
           onPressed: () {
            continueCallBack();
          },
        ),
        new FlatButton(
          child: Text("Cancel"),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
      ],
      ));
  }
}

您可以在 main(或任何您想要的地方)通过创建一个新方法来调用它,例如:

 _showDialog(BuildContext context)
{

  VoidCallback continueCallBack = () => {
 Navigator.of(context).pop(),
    // code on continue comes here

  };
  BlurryDialog  alert = BlurryDialog("Abort","Are you sure you want to abort this operation?",continueCallBack);


  showDialog(
    context: context,
    builder: (BuildContext context) {
      return alert;
    },
  );
}

【讨论】:

  • 您需要在用户选择继续选项后删除对话框。所以我需要添加 Navigator.of(context).pop(); continueCallback() 之后
  • @ReginaldoRigo 是的。我也必须将它添加到我的代码中。刚刚将其添加到答案中。
  • 这对我有用,但我必须将 BlurryDialog 转换为 StatefulWidget 并将 2 个字符串和 VoidCallback 声明为 final。
  • 如何使用 StatelessWidget 警告错误对话框?
【解决方案3】:

您可以使用此代码 sn-p 创建一个有两个按钮的警报框,

import 'package:flutter/material.dart';

class BaseAlertDialog extends StatelessWidget {

  //When creating please recheck 'context' if there is an error!

  Color _color = Color.fromARGB(220, 117, 218 ,255);

  String _title;
  String _content;
  String _yes;
  String _no;
  Function _yesOnPressed;
  Function _noOnPressed;

  BaseAlertDialog({String title, String content, Function yesOnPressed, Function noOnPressed, String yes = "Yes", String no = "No"}){
    this._title = title;
    this._content = content;
    this._yesOnPressed = yesOnPressed;
    this._noOnPressed = noOnPressed;
    this._yes = yes;
    this._no = no;
  }

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: new Text(this._title),
      content: new Text(this._content),
      backgroundColor: this._color,
      shape:
          RoundedRectangleBorder(borderRadius: new BorderRadius.circular(15)),
      actions: <Widget>[
        new FlatButton(
          child: new Text(this._yes),
          textColor: Colors.greenAccent,
          onPressed: () {
            this._yesOnPressed();
          },
        ),
        new FlatButton(
          child: Text(this._no),
          textColor: Colors.redAccent,
          onPressed: () {
            this._noOnPressed();
          },
        ),
      ],
    );
  }
}

要显示对话框,您可以有一个在导入BaseAlertDialog 类后调用它的方法 NB

_confirmRegister() {
var baseDialog = BaseAlertDialog(
    title: "Confirm Registration",
    content: "I Agree that the information provided is correct",
    yesOnPressed: () {},
    noOnPressed: () {},
    yes: "Agree",
    no: "Cancel");
showDialog(context: context, builder: (BuildContext context) => baseDialog);
}

输出将是这样的

【讨论】:

  • 如何在 onTap 函数上调用它?
  • 在 Suragch 的上述回答中,他提供了制作示例应用程序的所有代码,您可以在其中点击按钮并显示对话框。
【解决方案4】:

这是一个较短但完整的代码。

如果你需要一个只有一个按钮的对话框:

await showDialog(
      context: context,
      builder: (context) => new AlertDialog(
        title: new Text('Message'),
        content: Text(
                'Your file is saved.'),
        actions: <Widget>[
          new FlatButton(
            onPressed: () {
              Navigator.of(context, rootNavigator: true)
                  .pop(); // dismisses only the dialog and returns nothing
            },
            child: new Text('OK'),
          ),
        ],
      ),
    );

如果您需要带有是/否按钮的对话框:

onPressed: () async {
bool result = await showDialog(
  context: context,
  builder: (context) {
    return AlertDialog(
      title: Text('Confirmation'),
      content: Text('Do you want to save?'),
      actions: <Widget>[
        new FlatButton(
          onPressed: () {
            Navigator.of(context, rootNavigator: true)
                .pop(false); // dismisses only the dialog and returns false
          },
          child: Text('No'),
        ),
        FlatButton(
          onPressed: () {
            Navigator.of(context, rootNavigator: true)
                .pop(true); // dismisses only the dialog and returns true
          },
          child: Text('Yes'),
        ),
      ],
    );
  },
);

if (result) {
  if (missingvalue) {
    Scaffold.of(context).showSnackBar(new SnackBar(
      content: new Text('Missing Value'),
    ));
  } else {
    saveObject();
    Navigator.of(context).pop(_myObject); // dismisses the entire widget
  }
} else {
  Navigator.of(context).pop(_myObject); // dismisses the entire widget
}
}

【讨论】:

    【解决方案5】:

    只需使用此自定义对话框类,您不需要将其保留或使其为空,因此您可以轻松完成此自定义。

    import 'package:flutter/material.dart';
    
    class CustomAlertDialog extends StatelessWidget {
      final Color bgColor;
      final String title;
      final String message;
      final String positiveBtnText;
      final String negativeBtnText;
      final Function onPostivePressed;
      final Function onNegativePressed;
      final double circularBorderRadius;
    
      CustomAlertDialog({
        this.title,
        this.message,
        this.circularBorderRadius = 15.0,
        this.bgColor = Colors.white,
        this.positiveBtnText,
        this.negativeBtnText,
        this.onPostivePressed,
        this.onNegativePressed,
      })  : assert(bgColor != null),
            assert(circularBorderRadius != null);
    
      @override
      Widget build(BuildContext context) {
        return AlertDialog(
          title: title != null ? Text(title) : null,
          content: message != null ? Text(message) : null,
          backgroundColor: bgColor,
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(circularBorderRadius)),
          actions: <Widget>[
            negativeBtnText != null
                ? FlatButton(
                    child: Text(negativeBtnText),
                    textColor: Theme.of(context).accentColor,
                    onPressed: () {
                      Navigator.of(context).pop();
                      if (onNegativePressed != null) {
                        onNegativePressed();
                      }
                    },
                  )
                : null,
            positiveBtnText != null
                ? FlatButton(
                    child: Text(positiveBtnText),
                    textColor: Theme.of(context).accentColor,
                    onPressed: () {
                      if (onPostivePressed != null) {
                        onPostivePressed();
                      }
                    },
                  )
                : null,
          ],
        );
      }
    }
    

    用法:

    var dialog = CustomAlertDialog(
      title: "Logout",
      message: "Are you sure, do you want to logout?",
      onPostivePressed: () {},
      positiveBtnText: 'Yes',
      negativeBtnText: 'No');
    showDialog(
      context: context,
      builder: (BuildContext context) => dialog);
    

    输出:

    【讨论】:

      【解决方案6】:

      或者您可以为此使用 RFlutter Alert 库。它易于定制且易于使用。它的默认样式包括圆角,您可以根据需要添加任意数量的按钮。

      基本警报:

      Alert(context: context, title: "RFLUTTER", desc: "Flutter is awesome.").show();
      

      按钮提醒:

      Alert(
          context: context,
          type: AlertType.error,
          title: "RFLUTTER ALERT",
          desc: "Flutter is more awesome with RFlutter Alert.",
          buttons: [
          DialogButton(
              child: Text(
              "COOL",
              style: TextStyle(color: Colors.white, fontSize: 20),
              ),
              onPressed: () => Navigator.pop(context),
              width: 120,
          )
          ],
      ).show();
      

      你也可以定义generic alert styles

      *我是 RFlutter Alert 的开发者之一。

      【讨论】:

      • 不错。看起来它可以节省一些样板文件并且非常可定制。
      • 有没有办法将不同的函数传递给 Alert 的 onPressed 参数,这样我就不必不断为所有内容制作新的警报??
      【解决方案7】:

      如果您想要漂亮且响应迅速的警报对话框,那么您可以使用类似的颤振包

      rflutter alert ,fancy dialog,rich alert,sweet alert dialogs,easy dialog & easy alert

      这些警报外观漂亮且反应灵敏。其中 rflutter alert 是最好的。目前我正在为我的应用程序使用 rflutter alert。

      【讨论】:

      • 链接和包名会很有帮助
      • 我是 RFlutter Alert 开发人员,感谢您对@raman raman 的好评。
      【解决方案8】:
      showAlertDialog(BuildContext context, String message, String heading,
            String buttonAcceptTitle, String buttonCancelTitle) {
          // set up the buttons
          Widget cancelButton = FlatButton(
            child: Text(buttonCancelTitle),
            onPressed: () {},
          );
          Widget continueButton = FlatButton(
            child: Text(buttonAcceptTitle),
            onPressed: () {
      
            },
          );
      
          // set up the AlertDialog
          AlertDialog alert = AlertDialog(
            title: Text(heading),
            content: Text(message),
            actions: [
              cancelButton,
              continueButton,
            ],
          );
      
          // show the dialog
          showDialog(
            context: context,
            builder: (BuildContext context) {
              return alert;
            },
          );
        }
      

      像这样称呼:

      showAlertDialog(context, 'Are you sure you want to delete?', "AppName" , "Ok", "Cancel");
      

      【讨论】:

        【解决方案9】:

        查看Flutter Dropdown Banner 可以轻松提醒用户事件和提示操作,而无需管理呈现、延迟和关闭组件的复杂性。

        设置:

        import 'packages:dropdown_banner/dropdown_banner.dart';
        ...
        class MainApp extends StatelessWidget {
          ...
          @override
          Widget build(BuildContext context) {
            final navigatorKey = GlobalKey<NavigatorState>();
            ...
            return MaterialApp(
                ...
                home: DropdownBanner(
                  child: Scaffold(...),
                  navigatorKey: navigatorKey,
                ),
            );
          }
        }
        

        使用它:

        import 'packages:dropdown_banner/dropdown_banner.dart';
        ...
        class SomeClass {
          ...
          void doSomethingThenFail() {
            DropdownBanner.showBanner(
              text: 'Failed to complete network request',
              color: Colors.red,
              textStyle: TextStyle(color: Colors.white),
            );
          }
        }
        
        点击here查看示例

        【讨论】:

        • 当发布链接作为答案时,尝试添加一些实际的文本/代码来解释您提供链接的原因,和/或如何使用链接的内容。否则,此类回复应为 cmets。
        • @Adrian 我根据您的建议添加了一些示例代码。
        【解决方案10】:

        显示对话框的另一个简单选项是使用stacked_services

         _dialogService.showDialog(
              title: "Title",
              description: "Dialog message Tex",
                 );
             });
        

        【讨论】:

          猜你喜欢
          • 2019-01-28
          • 2019-06-25
          • 2020-03-05
          • 2020-07-02
          • 2021-08-26
          • 2019-05-29
          • 2020-07-25
          • 2018-08-28
          相关资源
          最近更新 更多