【问题标题】:Flutter: Added an additional TextFormField to Column but no change in displayFlutter:向 Column 添加了一个额外的 TextFormField 但显示没有变化
【发布时间】:2020-08-11 23:16:15
【问题描述】:

我正在制作一个表格,它以表格为子。 有一个按钮可以添加额外的 Column,另一个按钮可以添加额外的 TextFormField。按钮实现为 _MyHomePageState。

所以,设置就像下面链接中的设置。

https://flutter.dev/docs/development/ui/interactive#the-parent-widget-manages-the-widgets-state

当调用 addTextFormField 方法时,一个新的 TextFormField 被添加到 List _textFormFields。 List _columns 将 _textFormFields 作为子项。因此,_columns 也发生了变化。 _columns 然后通过 build 传递给 FormA 构造函数。

此时,_columns 中有 1 个 Column Widget,Column Widget 中有 2 个 TextFormFields。但是,它只显示 1 个 TextFormField。

然后当我按下 addColumn 按钮时,会出现一个带有两个 TextFormFields 的附加列。

为什么我按addTextFormField时没有2个TextFormFields?

main.dart

    class _MyHomePageState extends State<MyHomePage> {

      List<Widget> _columns;
      List<Widget> _textFormFields;

      @override
      void initState(){
        super.initState();
          _columns = List<Widget>();
          _textFormFields = List<Widget>();

          _addTextFormField();
          _addColumn();
      }

      void _addTextFormField() async {
          _textFormFields.add(TextFormField(
                        decoration: InputDecoration(
                        hintText: _textFormFields.length.toString()),
                        ),
                      );

          for(Column column in _columns){
            print('from _addTextFormField ' + column.children.length.toString()); 
           // press addTextFormField button once, it prints  2

            print('from _addTextFormField ' + column.children.toString()); 
           //press addTextFormField button once, it prints [TextFormField, TextFormField]
          }

          setState((){

          });
      }

      void _addColumn() async {

          print('from addColumn   no. of textFormFields ' + _textFormFields.length.toString());
          _columns.add(Column(
                      children: _textFormFields,),
                      );

          for(Column column in _columns){
            print('from addColumn   no. of widget in a column ' + column.children.length.toString());
          }

          setState((){
          });
      }

      @override
      Widget build(BuildContext context) {

        print('rebuild');
        // press addTextFormField button once, it prints rebuild
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                FormA (columns : _columns),
              ],
            ),
          ),

          floatingActionButton: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
                FloatingActionButton(
                  onPressed: _addColumn,
                  tooltip: '+C',
                  child: Icon(Icons.add),
                ),
                FloatingActionButton(
                  onPressed: _addTextFormField,
                  tooltip: '+R',
                  child: Icon(Icons.add),
                ),
            ],
          ),


        );
      }
    }

formA.dart

class FormA extends StatelessWidget{

  FormA({Key key, this.columns})
      : super(key: key);

  List<Widget> columns;

  @override
  Widget build(BuildContext context) {

      for(Column column in columns){
        print('from FormA   no. of widget in a column ' + column.children.length.toString());
       // press addTextFormField button once, it prints 2
        print('from FormA ' + column.children.toString());
       // press addTextFormField button once, it prints [TextFormField, TextFormField]
      }

    return Form(
      child: Table(
        children: [TableRow(
          children: columns,
        ),],
      ),
    );
  }
}

【问题讨论】:

    标签: forms flutter dart flutter-web


    【解决方案1】:

    您当前形式的代码将无法按预期工作,因为即使 _columns 列表引用了 _textFormFields,您最初构建的 Column 小部件的 children 已经构建并且不会更改如果您更改它 MyhomePage 小部件,因为它不会有它的引用。

    在当前的形式中,您的代码是这样工作的。

    您需要做的就是在 setState_addTextFormField 方法中重新分配 _columns 字段,这将像这样重建整个列列表。

    
    void _addTextFormField() {
        _textFormFields.add(
          TextFormField(
            decoration:
                InputDecoration(hintText: _textFormFields.length.toString()),
          ),
        );
    
        for (Column column in _columns) {
          print('from _addTextFormField ' + column.children.length.toString());
          // press addTextFormField button once, it prints  2
    
          print('from _addTextFormField ' + column.children.toString());
          //press addTextFormField button once, it prints [TextFormField, TextFormField]
    
        }
    
        setState(() {
          _columns = List<Column>.generate(
              _columns.length, (index) => Column(children: _textFormFields));
        });
      }
    

    修改后会是这个样子。

    这是一个带有解决方案的实时代码笔。

    https://codepen.io/abhilas-csc/pen/dyYRVrL

    【讨论】:

    • 谢谢!你能解释一下为什么 Column 小部件没有对 _textFormFields 的引用吗?当最初调用 _addColumn 时,我将 _textFormFields 分配为 Column 小部件的子小部件。当再次调用 _addTextFormField 时,它会在 FormA 的“built”方法中打印 [TextFormField, TextFormField]。不是说 _columns 里面的 Column 小部件还有引用吗?
    • 因为 Flutter 中的小部件是不可变的。检查此link 以获取MultiChildRenderObjectWidget 的文档,这是Column 类实现的内容。在 cmets 中明确提到了为什么这是不可能的。
    • 我认为这是必要的原因之一是,必须重建 Column 小部件才能有效地计算如何布局其子级。
    【解决方案2】:

    然后当我按下 addColumn 按钮时,一个额外的 Column 有两个 TextFormFields 将会出现。

    为什么我按addTextFormField时没有2个TextFormFields?

    真的没有!当小部件初始化时,每个列表中只有一个Column 和一个TextFormField。现在您按addColumn,这样又添加了一个Column。所以你有两个Columns,但还有一个TextFormField

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多