如何在 Flutter 中刷新 AlertDialog?
Posted
技术标签:
【中文标题】如何在 Flutter 中刷新 AlertDialog?【英文标题】:How to refresh an AlertDialog in Flutter? 【发布时间】: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),
),
【问题讨论】:
【参考方案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+ 非常有用,谢谢以上是关于如何在 Flutter 中刷新 AlertDialog?的主要内容,如果未能解决你的问题,请参考以下文章