我在对话框中打印来自TextField的输入(TextField和输出都在AlertDialog中)。仅当我在键盘上按“完成”时,输出才会更新。如果我不按“完成”,它将继续显示旧的输出。
这是我的源代码:
Future<void> widePopUpCustom() async {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Enter Number'),
content: SingleChildScrollView(
child: ListBody(children: <Widget>[
TextField(
controller: customRun,
decoration: InputDecoration(
labelText: 'Number',
)),
Text('${customRun.text}'),
])),
actions: <Widget>[
FlatButton(
child: Text('OK'), onPressed: () => Navigator.pop(context))
]);
});
}
我也已经声明了控制器:
final TextEditingController customRun = TextEditingController();
(进一步说明)这是我想实时更新的输出,同时在TextField中输入文本,而无需按键盘上的完成
Text('${customRun.text}'),
答案 0 :(得分:2)
对于演示,您可以在这里查看。 Example
首先,我们希望此小部件内的内容将根据用户类型进行重建。
Text('${customRun.text}'),
不幸的是,此小部件以如下方式驻留在widePopUpCustom方法内: 警报对话框的孩子
void widePopUpCustom() async {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Enter Number'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
TextField(
controller: customRun,
decoration: InputDecoration(
labelText: 'Number',
),
),
Text('${customRun.text}'), // Needs to be re-rendered
],
),
),
);
},
);
}
在这种情况下,我们无法在AlertDialog
小部件(包括其所有子级ListBody
,TextField
和Text
小部件上)触发重建。
AlertDialog
并将其转换为有状态小工具我们考虑将AlertDialog
移至AlertWrapper
,并将AlertWrapper
定义为有状态小工具。因此,稍后,我们可以使用以下代码触发AlertWrapper
的重建:
setState((){})
我们可以完成此步骤,将widePopUpCustom()
修改为:
Future<void> widePopUpCustom() async {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertWrapper();
},
);
}
之前,AlertDialog将被视为无状态,除非我们关闭对话框,否则不会重新渲染该对话框。
通过使用有状态的小部件,我们可以探索initState的用法。在这种情况下,我们将addListener
附加到customRun
TextController。
请注意changesOnField方法。每次用户与键盘输入进行交互时都会触发此方法
class AlertWrapper extends StatefulWidget {
const AlertWrapper({
Key key,
}) : super(key: key);
@override
_AlertWrapperState createState() => _AlertWrapperState();
}
class _AlertWrapperState extends State<AlertWrapper> {
final TextEditingController customRun = TextEditingController();
changesOnField() {
print("Updated Text: ${customRun.text}");
setState(() {}); // Will re-Trigger Build Method
}
@override
void initState() {
super.initState();
customRun.addListener(changesOnField);
}
}
changesOnField将触发重新调用生成方法,然后我们可以更新Text小部件中的值
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Enter Number'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
TextField(
controller: customRun,
decoration: InputDecoration(
labelText: 'Number',
),
),
Text('${customRun.text}'), // Finally re-rendered
],
),
),
您可以查看此仓库。 Github
如official docs所述,我们需要配置侦听器以优化应用程序。
稍后我们可以添加此代码
@override
void dispose() {
customRun.dispose();
super.dispose();
}
答案 1 :(得分:0)
您需要为文本字段添加onChanged(txt)
方法,并且必须在其中包含setState()
以便每次键入字符时刷新文本
Future<void> widePopUpCustom() async {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Enter Number'),
content: SingleChildScrollView(
child: ListBody(children: <Widget>[
TextField(
controller: customRun,
decoration: InputDecoration(
labelText: 'Number',
)),
onChanged:(txt){
setState((){
customRun.text = txt;
}),
},
Text('${customRun.text}'),
])),
actions: <Widget>[
FlatButton(
child: Text('OK'), onPressed: () => Navigator.pop(context))
]);
});
}