当表单滚动到屏幕外时,每个表单字段的丢失状态?

时间:2017-11-21 09:08:11

标签: flutter

当表单滚动到屏幕外时,如何保存每个表单字段的状态?当我向上滚动时,我丢失了我在 TextFormFields 中键入的值字段在屏幕外。

我听说过将它保存在控制器中然后分配给TextFormField的initialvalue的建议,如代码所示,但它对我不起作用。我错过了什么?

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'),
                ),
              ],)
          )
      ),
    );
  }

4 个答案:

答案 0 :(得分:1)

  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;
                      },
                    ),
                  ),
                ),

答案 1 :(得分:1)

在使用TextFormField时,您不需要那样使用initialValue。实际上,如果_controller.text为null,则会给出断言错误。

要使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
            ],
          ))),
    );
  }
}

答案 2 :(得分:0)

每个TextEditingController都需要专门的TextFormField,我认为您不需要在这些字段上使用initialValue属性。

看一下这个答案https://stackoverflow.com/a/45242235/6414732,这也许有帮助。

答案 3 :(得分:0)

有两种解决方案:

  1. 防止对象被回收
  2. 将状态保存在父窗口小部件中

因此,尽管TextFormField派生自其中的FormField是有状态的,但将其放入任何描述的列表中将有重建它的风险。

选项1:

List更改为Column并将其包装在ListSingleChildListView中,它既快捷又容易破解,但可能会影响很多商品的性能 >

List(
   children: [...]
)

nb。如果您有listview.builder,则需要将其映射出来而不使用该生成器,否则请转到选项2。

SingleChildScrollView(
   child: Column(
       children: [...]
   )
)

选项2:

为每个字段创建一个控制器并将其保存在父窗口小部件中,或将数据保存到地图并设置其初始数据。您可以解决它,但是无论哪种方式都需要将其保存在父窗口小部件中。