当表单滚动到屏幕外时,每个表单字段的状态会丢失吗?
Posted
技术标签:
【中文标题】当表单滚动到屏幕外时,每个表单字段的状态会丢失吗?【英文标题】:Losing state of each form field when the form is scrolled off screen? 【发布时间】:2017-11-21 09:08:11 【问题描述】:当表单滚动离开屏幕时,如何保存每个表单字段的状态?当我向上滚动时,我会丢失在 TextFormFields 中输入的值,并且字段不在屏幕上。
我听说过将其保存在控制器中然后分配给 TextFormField 的初始值的建议,如代码中所示,但它对我不起作用。我错过了什么?
TextEditingController _controller = new TextEditingController();
@override
Widget build(BuildContext context)
return new Scaffold(
key: scaffoldKey,
appBar: new AppBar(
title: new Text('Enter Vehicle'),
),
body: new Padding(
padding: const EdgeInsets.all(16.0),
child: new Form(
key: formKey,
child: new ListView(children: <Widget>[
new TextFormField(
decoration: new InputDecoration(labelText: 'Vehicle Number'),
controller: _controller,
initialValue: _controller.text,
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Tag'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Make'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Model'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Year'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Vehicle Type'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Location'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Fuel'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Other'),
),
new TextFormField(
decoration: new InputDecoration(labelText: 'Your password'),
validator: (val) =>
val.length < 6 ? 'Password too short.' : null,
onSaved: (val) => _password = val,
obscureText: true,
),
new RaisedButton(
onPressed: _submit,
child: new Text('Login'),
),
],)
)
),
);
【问题讨论】:
【参考方案1】:有两种解决方案:
-
防止物品回收
在父窗口小部件中保存状态
因此,虽然从 TextFormField 派生的 FormField 是有状态的,但将其放入任何描述的列表中都会有重建它的风险。
选项 1:
将List
更改为Column
并将其包装在List
或SingleChildListView
中,它既快速又笨拙,但对于许多项目可能存在一些性能问题
List(
children: [...]
)
注意。如果您有一个 listview.builder,您将需要将其映射出来,而不是使用该构建器,或者转到选项 2。
到
SingleChildScrollView(
child: Column(
children: [...]
)
)
选项 2:
为每个字段创建一个控制器并将其保存在父窗口小部件中,或者将数据保存到地图并设置其初始数据。您可以解决它,但无论哪种方式,您都需要将其保存在父小部件中。
【讨论】:
【参考方案2】:在使用 TextFormField 时,您不需要以这种方式使用 initialValue。事实上,如果_controller.text
为空,它会给出一个断言错误。
要让 TextFormFields 正常工作,请确保:
您在每个字段上使用不同的 TextEditingController。 您正在处理完成后的 TextEditingController。 您的表单位于 StatefulWidget 中。工作示例:
class MyForm extends StatefulWidget
@override
_MyFormState createState() => _MyFormState();
class _MyFormState extends State<MyForm>
TextEditingController _vehicleNumber;
@override
void initState()
super.initState();
_vehicleNumber = new TextEditingController();
@override
void dispose()
super.dispose();
_vehicleNumber.dispose();
@override
Widget build(BuildContext context)
return new Scaffold(
appBar: new AppBar(
title: new Text('Enter Vehicle'),
),
body: new Padding(
padding: const EdgeInsets.all(16.0),
child: new Form(
child: new ListView(
children: <Widget>[
new TextFormField(
decoration: new InputDecoration(labelText: 'Vehicle Number'),
controller: _vehicleNumber,
),
// All the other fields here
// All should have its own controller
],
))),
);
【讨论】:
【参考方案3】:您需要为每个TextFormField
指定一个专用的TextEditingController
,我认为您不需要在字段上使用initialValue
属性。
看看这个答案https://***.com/a/45242235/6414732,这可能也会有所帮助。
【讨论】:
这看起来很痛苦。 不使用表单字段而是制作自定义“react-form”会更容易。 或者也许不要使用 ListView,一旦它们看不见,它就会从小部件树中删除元素。只要列表不是数百个字段,这应该不是问题。 其实我已经试过了。我在每个 TextFormField 上都有一个 TextEditingController。在 build() 中,我将每个字段的控制器分配给相关的字段值,然后将每个字段值分配给相关的 TextFormField 的初始值。然而,即便如此,除非调用 setState 来保持值,否则它仍然不起作用。感觉不对。我知道他们有开放的票来改进表单的处理方式。这比我想象的要大得多。在某些时候可能会出现更好的解决方案。与此同时,我将使用我的 hacky 解决方案。【参考方案4】: new Container(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 0.0, bottom: 0.0),
child: new EnsureVisibleWhenFocused(
focusNode: _focusNode_nooftickets,
child: new TextFormField(
controller: _ticketscontroller,
initialValue: _ticketscontroller.text,
focusNode: _focusNode_nooftickets,
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly
],
validator: validatenooftickets,
onSaved: (String value)
ticketmode.nooftickets = value;
,
),
),
),
【讨论】:
以上是关于当表单滚动到屏幕外时,每个表单字段的状态会丢失吗?的主要内容,如果未能解决你的问题,请参考以下文章