【问题标题】:How to refresh an AlertDialog in Flutter?如何在 Flutter 中刷新 AlertDialog?
【发布时间】:2019-01-28 10:39:55
【问题描述】:

目前,我有一个AlertDialog 和一个IconButton。用户可以点击 IconButton,每次点击我都有两种颜色。问题是我需要关闭 AlertDialog 并重新打开才能看到颜色图标的状态变化。我想在用户单击时立即更改 IconButton 颜色。

代码如下:

bool pressphone = false;
//....
new IconButton(
   icon: new Icon(Icons.phone),
   color: pressphone ? Colors.grey : Colors.green,
   onPressed: () => setState(() => pressphone = !pressphone),
),

【问题讨论】:

    标签: flutter dart flutter-layout flutter-alertdialog


    【解决方案1】:

    如果您通过 View Models 将数据与 UI 分离并使用 Provider 包和 ChangeNotifier,则需要像这样在调用对话框的小部件中包含当前模型:

    showDialog(context: context, builder: (dialog) {
                  return ChangeNotifierProvider.value(
                      value: context.read<ViewModel>(),
                    child: CustomStatefulDialogWidget(),
                  );
                },
    

    请注意,可能有更简洁的方法可以做到这一点,但这对我有用。

    关于Provider的其他信息:https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

    【讨论】:

      【解决方案2】:

      在 AlertDialog 的 content 部分中使用 StatefulBuilder。甚至StatefulBuilder docs 实际上也有一个带有对话框的示例。

      它的作用是为您提供一个新的context,以及在需要时重建的setState函数。

      示例代码:

      showDialog(
        context: context,
        builder: (BuildContext context) {
      
          int selectedRadio = 0; // Declare your variable outside the builder
          
          return AlertDialog( 
            content: StatefulBuilder(  // You need this, notice the parameters below:
              builder: (BuildContext context, StateSetter setState) {
                return Column(  // Then, the content of your dialog.
                  mainAxisSize: MainAxisSize.min,
                  children: List<Widget>.generate(4, (int index) {
                    return Radio<int>(
                      value: index,
                      groupValue: selectedRadio,
                      onChanged: (int value) {
                        // Whenever you need, call setState on your variable
                        setState(() => selectedRadio = value);
                      },
                    );
                  }),
                );
              },
            ),
          );
        },
      );
      

      正如我所提到的,这就是showDialog docs 上所说的:

      [...] 构建器返回的小部件不与位置共享上下文 该 showDialog 最初是从中调用的。 使用 StatefulBuilder 或 如果对话框需要动态更新,则自定义 StatefulWidget

      【讨论】:

      • 完美!卡在这上面好久了!
      【解决方案3】:

      使用 StatefulBuilder 在 Dialog 内部使用 setState 并仅在其中更新 Widget。

      showDialog(
        context: context,
        builder: (context) {
          String contentText = "Content of Dialog";
          return StatefulBuilder(
            builder: (context, setState) {
              return AlertDialog(
                title: Text("Title of Dialog"),
                content: Text(contentText),
                actions: <Widget>[
                  TextButton(
                    onPressed: () => Navigator.pop(context),
                    child: Text("Cancel"),
                  ),
                  TextButton(
                    onPressed: () {
                      setState(() {
                        contentText = "Changed Content of Dialog";
                      });
                    },
                    child: Text("Change"),
                  ),
                ],
              );
            },
          );
        },
      );
      

      【讨论】:

      • 这是正确答案,我从没想过你可以'subClass\subOverload' [setState] live saviour
      • 也不适合我。有没有人可以解释为什么它对某些人不起作用?
      • 我正在使用 Dart 2.8.1 和 Flutter 1.19.0-0.0.pre,它在 WEB 中按预期工作,谢谢 :)
      • @MutluSimsek 当您尝试 setState 一个在 StatefulBuilder/StatefulWidget 之外声明的变量时,它不起作用
      • 谢谢。它对我有用。但是,如果我从外部单独的方法在有状态的构建器中添加任何孩子,它就不起作用。然后,如果我直接在有状态的构建器中添加孩子,它就可以工作。更改有状态构建器中的变量是可行的。如果它在有状态构建器之外,则它不起作用。
      【解决方案4】:

      首先你需要使用StatefulBuilder。然后我设置_setState 变量,它甚至可以在StatefulBuilder 之外使用,以设置新状态。

      StateSetter _setState;
      String _demoText = "test";
      
      showDialog(
        context: context,
        builder: (BuildContext context) {
      
          return AlertDialog( 
            content: StatefulBuilder(  // You need this, notice the parameters below:
              builder: (BuildContext context, StateSetter setState) {
                _setState = setState;
                return Text(_demoText);
              },
            ),
          );
        },
      );
      

      _setState 的使用方式与 setState 方法相同。比如这样:

      _setState(() {
          _demoText = "new test text";
      });
      

      【讨论】:

      • 这项工作非常适合我,这是我发现能够从对话框代码外部更新对话框内容的唯一方法。
      【解决方案5】:

      目前要检索我使用的 Dialog 的值

      showDialog().then((val){
      setState (() {}); 
      print (val);
      });
      

      示例 第一个屏幕

          onPressed: () { 
          showDialog(
             context: context,
             barrierDismissible: false,
             builder: (context) {
               return AddDespesa();
             }).then((val) {
               setState(() {});
               print(val);
              }
          );
         }
      

      第二屏

      AlertDialog(
          title: Text("Sucesso!"),
          content: Text("Gasto resgristrado com sucesso"),
          actions: <Widget>[
          FlatButton(
            child: Text("OK"),
            onPressed: () {
               Navigator.pop(context, true);
            },
           ),
         ],
       );
      

      将被打印出来,

      【讨论】:

      • 这并没有真正改变对话框的状态,因为对话框有自己的状态,使用常规的 setState 真的解决不了任何问题。
      【解决方案6】:

      这是因为您需要将您的 AlertDialog 放在它自己的 StatefulWidget 中,并将所有状态操作逻辑移到那里的颜色上。

      更新:

      void main() => runApp(MaterialApp(home: Home()));
      
      class Home extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return Scaffold(
              body: Center(
                  child: RaisedButton(
            child: Text('Open Dialog'),
            onPressed: () {
              showDialog(
                  context: context,
                  builder: (_) {
                    return MyDialog();
                  });
            },
          )));
        }
      }
      
      class MyDialog extends StatefulWidget {
        @override
        _MyDialogState createState() => new _MyDialogState();
      }
      
      class _MyDialogState extends State<MyDialog> {
        Color _c = Colors.redAccent;
        @override
        Widget build(BuildContext context) {
          return AlertDialog(
            content: Container(
              color: _c,
              height: 20.0,
              width: 20.0,
            ),
            actions: <Widget>[
              FlatButton(
                  child: Text('Switch'),
                  onPressed: () => setState(() {
                        _c == Colors.redAccent
                            ? _c = Colors.blueAccent
                            : _c = Colors.redAccent;
                      }))
            ],
          );
        }
      }
      

      【讨论】:

      • 谢谢,我尝试创建另一个 stful 小部件类,但是当我按下按钮调用我的 Widet 时,我什么都没有。 Normaly 当我调用我的 alertdialog stfull 小部件时它返回这个 @override Widget build(BuildContext context) { return new AlertDialog( content: new Container ....
      • 我正在尝试扩展它以更改对话框的“确定”操作按钮的启用/禁用状态。但我还没有任何成功。有什么建议吗?
      • 这是最好的方法!
      • 完美的解决方案,用于创建有状态的 AlertDialog。应该是公认的答案,因为这为代码重构而不是嵌套代码块提供了更多选项。谢谢你的干净答案。 50+
      • 非常有用,谢谢
      猜你喜欢
      • 2020-04-10
      • 2012-02-11
      • 2019-05-19
      • 2019-06-25
      • 1970-01-01
      • 2019-05-21
      • 2020-07-02
      • 2021-08-26
      相关资源
      最近更新 更多