选择TextField后的窗口小部件重建Flutter

Nad*_*x56 10 forms textfield dart flutter

我正在开发需要具有表单的Flutter应用程序。因此,当用户打开应用程序时,启动屏幕将显示在具有以下代码的表单之前:

import 'package:flutter/material.dart';
import '../model/User.dart';
import './FileManager.dart';
import './MyListPage.dart';

class UserLoader extends StatefulWidget {
  @override
  _UserLoaderState createState() => new _UserLoaderState();
}

class _UserLoaderState extends State<UserLoader> {
  final userFileName = "user_infos.txt";
  User _user;

  @override
  Widget build(BuildContext context) {
    print("build UserLoader");
    final _formKey = new GlobalKey<FormState>();
    final _firstNameController = new TextEditingController();
    final _lastNameController = new TextEditingController();
    final _emailController = new TextEditingController();
    final _phoneController = new TextEditingController();

    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Informations"),
          actions: <Widget>[
            new IconButton(
                icon: const Icon(Icons.save),
                onPressed: () {
                  _user = _onFormValidate(
                      _formKey.currentState,
                      _firstNameController.text,
                      _lastNameController.text,
                      _emailController.text,
                      _phoneController.text);
                })
          ],
        ),
        body: new Center(
          child: new SingleChildScrollView(
              child: new Form(
                  key: _formKey,
                  child: new Column(children: <Widget>[
                    new ListTile(
                      leading: const Icon(Icons.person),
                      title: new TextFormField(
                        decoration: new InputDecoration(
                          hintText: "Prénom",
                        ),
                        keyboardType: TextInputType.text,
                        controller: _firstNameController,
                        validator: _validateName,
                      ),
                    ),
                    new ListTile(
                      leading: const Icon(Icons.person),
                      title: new TextFormField(
                        decoration: new InputDecoration(
                          hintText: "Nom",
                        ),
                        keyboardType: TextInputType.text,
                        controller: _lastNameController,
                        validator: _validateName,
                      ),
                    ),
Etc, etc ...
Run Code Online (Sandbox Code Playgroud)

但是,当我点击TextField时,键盘立即出现并关闭,并且所有组件都已重建。因此,我无法填写表格。

有人可以解决吗?提前致谢 !

rbp*_*rbp 13

您尚未为此提供完整的代码,所以我不知道上下文是什么。

我自己陷入的一个陷阱(从我的描述中可以得出,这可能会影响到您)是将一个有状态的窗口小部件嵌套在另一个有状态的窗口小部件中。

例如,

class Parent extends StatefulWidget {
  @override
  ParentState createState() => ParentState();

  (...)
}

class ParentState extends State<Parent> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Child(),
    );
  }

  (...)
}

class Child extends StatefulWidget {
  @override
  ChildState createState() => ChildState();

  (...)
}

class ChildState extends State<Child> {
  @override
  Widget build(BuildContext context) {
    return TextField(...);
  }

  (...)
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是,重新生成Parent意味着ParentState().build()运行该对象,并创建一个具有新对象的 Child实例ChildState。这将重置所有内容。

尝试不重新创建ChildWidget,而是将其保存在ParentState上,如下所示:

class Parent extends StatefulWidget {
  @override
  ParentState createState() => ParentState();

  (...)
}

class ParentState extends State<Parent> {
  Child _child;

  @override
  void initState() {
    _child = Child();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: child,
    );
  }

  (...)
}
// The rest remains the same
Run Code Online (Sandbox Code Playgroud)

编辑:您只需要记住,如果您的窗口小部件树稍微复杂一点,则可能需要1)传递来自Parent的回调以通知状态更改,以及2)别忘了还要在setState()上调用儿童。

  • 很好的解决方法,但是当孩子的构建使用 FutureBuilder 时,您将如何处理?谢谢 (4认同)