如何在 Flutter 中制作 AlertDialog?

Posted

技术标签:

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

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

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

How to style AlertDialog Actions in Flutter adding dropdown menu in alert dialog box in flutter Show alert dialog on app main screen load automatically how to refresh alertdialog in flutter Alert Dialog with Rounded corners in flutter

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

【问题讨论】:

必须看看这个,这里是创建这个的确切代码:-***.com/a/63086647/10563627 使用警报对话框的最佳方法是为警报对话框创建一个单独的类,并在整个项目中使用它。参考这个:arkapp.medium.com/… 【参考方案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.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",
         );
     );

【讨论】:

以上是关于如何在 Flutter 中制作 AlertDialog?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 制作漂亮的登录表单

如何在 Flutter 中制作适合所有屏幕的列

Flutter 如何在 Android Studio 中制作发布版本?

如何在 Flutter 中制作这个自定义 RangeSlider?

如何在 Flutter 中使用全局键制作 StatefulWidget?

如何在 Flutter 中制作密码验证动画