Flutter-单击添加新的小部件

Cam*_*ira 2 android dart flutter flutter-layout

我是新手,我正在尝试构建一个相当简单的应用程序。我有这个简单的代码(仍在进行中),我试图在用户每次单击按钮时添加一个新的小部件。

这是我的代码:

class ResponsavelProfilePage extends StatefulWidget {
  @override
  _ResponsavelProfilePageState createState() => new _ResponsavelProfilePageState();
}

class _ResponsavelProfilePageState extends State<ResponsavelProfilePage> {

  int _count = 1;

  @override
  Widget build(BuildContext context) {
    List<Widget> _contatos = new List.generate(_count, (int i) => new ContactRow());

    return new Scaffold(
        appBar: new AppBar(
          title: new Text(GlobalConstants.appName),
        ),
        body: new LayoutBuilder(builder: (context, constraint) {
          final _maxHeight = constraint.biggest.height / 3;
          final _biggerFont = TextStyle(fontSize: _maxHeight / 6);

          return new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Nome',
                  ),
                ),
                new Container(
                  padding: new EdgeInsets.all(20.0),
                ),
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Data de nascimento',
                  ),
                ),
                new Container(
                  padding: new EdgeInsets.all(20.0),
                ),
                new Row(
                  children: _contatos,
                ),
                new FlatButton(
                    onPressed:  _addNewContactRow,
                  child: new Icon(Icons.add),
                ),
                //new ContactRow()
              ],
            ),
          );
        })
    );
  }

  void _addNewContactRow() {
    setState(() {
      _count = _count + 1;
    });
  }
}

class ContactRow extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _ContactRow();

}

class _ContactRow extends State<ContactRow> {
  @override
  Widget build(BuildContext context) {
    return new Container(
        child:
        new Column(
            children: <Widget>[
              new TextFormField(
                decoration: new InputDecoration(
                  labelText: 'Contato',
                ),
              ),
              new Text("Tipo Contato: "),
              new DropdownButton(
                value: _currentContactType,
                items: _dropDownMenuItems,
                onChanged: changedDropDownItem,
              ),
              new Container(
                padding: new EdgeInsets.all(20.0),
              ),
            ]
        )
    );
  }

  List _contactTypes =
  ["Phone (SMS)", "Phone (Whatsapp)", "Email"];

  List<DropdownMenuItem<String>> _dropDownMenuItems;
  String _currentContactType;

  @override
  void initState() {
    _dropDownMenuItems = getDropDownMenuItems();
    _currentContactType = null;
    super.initState();
  }

  List<DropdownMenuItem<String>> getDropDownMenuItems() {
    List<DropdownMenuItem<String>> items = new List();
    for (String city in _contactTypes) {
      items.add(new DropdownMenuItem(
          value: city,
          child: new Text(city)
      ));
    }
    return items;
  }

  void changedDropDownItem(String selectedCity) {
    setState(() {
      _currentContactType = selectedCity;
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

当用户在onPressed上使用addNewContactRow()单击该平面按钮时,我想添加另一个ContactRow。我已经在addNewContactRow()上找到了代码,在这里的另一个问题上找到了List.generate部分,但是我无法使其工作。

有人可以帮忙吗?

Aja*_*mar 13

只需用 ListView 替换 Row。

还对高度/宽度进行了一些更改,请检查一下。

结果 : 在此处输入图片说明 编码 :

import 'package:flutter/material.dart';

void main() => runApp(
      new MaterialApp(
        home: new ResponsavelProfilePage(),
      ),
    );

class ResponsavelProfilePage extends StatefulWidget {
  @override
  _ResponsavelProfilePageState createState() =>
      new _ResponsavelProfilePageState();
}

class _ResponsavelProfilePageState extends State<ResponsavelProfilePage> {
  int _count = 1;

  @override
  Widget build(BuildContext context) {
    List<Widget> _contatos =
        new List.generate(_count, (int i) => new ContactRow());

    return new Scaffold(
        appBar: new AppBar(
          title: new Text("NonstopIO"),
        ),
        body: new LayoutBuilder(builder: (context, constraint) {
          final _maxHeight = constraint.biggest.height / 3;
          final _biggerFont = TextStyle(fontSize: _maxHeight / 6);

          return new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Nome',
                  ),
                ),
                new Container(
                  padding: new EdgeInsets.all(20.0),
                ),
                new TextFormField(
                  decoration: new InputDecoration(
                    labelText: 'Data de nascimento',
                  ),
                ),
                new Container(
                  padding: new EdgeInsets.all(20.0),
                ),
                new Container(
                  height: 200.0,
                  child: new ListView(
                    children: _contatos,
                    scrollDirection: Axis.horizontal,
                  ),
                ),
                new FlatButton(
                  onPressed: _addNewContactRow,
                  child: new Icon(Icons.add),
                ),
                //new ContactRow()
              ],
            ),
          );
        }));
  }

  void _addNewContactRow() {
    setState(() {
      _count = _count + 1;
    });
  }
}

class ContactRow extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _ContactRow();
}

class _ContactRow extends State<ContactRow> {
  @override
  Widget build(BuildContext context) {
    return new Container(
        width: 170.0,
        padding: new EdgeInsets.all(5.0),
        child: new Column(children: <Widget>[
          new TextFormField(
            decoration: new InputDecoration(
              labelText: 'Contato',
            ),
          ),
          new Text("Tipo Contato: "),
          new DropdownButton(
            value: _currentContactType,
            items: _dropDownMenuItems,
            onChanged: changedDropDownItem,
          ),
          new Container(
            padding: new EdgeInsets.all(20.0),
          ),
        ]));
  }

  List _contactTypes = ["Phone (SMS)", "Phone (Whatsapp)", "Email"];

  List<DropdownMenuItem<String>> _dropDownMenuItems;
  String _currentContactType;

  @override
  void initState() {
    _dropDownMenuItems = getDropDownMenuItems();
    _currentContactType = null;
    super.initState();
  }

  List<DropdownMenuItem<String>> getDropDownMenuItems() {
    List<DropdownMenuItem<String>> items = new List();
    for (String city in _contactTypes) {
      items.add(new DropdownMenuItem(value: city, child: new Text(city)));
    }
    return items;
  }

  void changedDropDownItem(String selectedCity) {
    setState(() {
      _currentContactType = selectedCity;
    });
  }
}
Run Code Online (Sandbox Code Playgroud)


Tre*_*ree 5

这是做到这一点的一种方法

首先,让我们看看什么是children列的属性。

List<Widget> children: const <Widget> []

它是ListWidget。由于Flutter UI是用代码内置的,因此我们可以传递之前构造的子代数组。无需[]每次都声明它,当您希望在内部有动态子级ColumnRow

在您的构建器中,您返回Center包装列的窗口小部件。由于builder是一个函数,因此我们可以在返回Widget之前做一些魔术。

让我们首先从Column本身的一个变量中提取数组:

  List<Widget> extractedChildren = <Widget>[
    new TextFormField(
      decoration: new InputDecoration(
        labelText: 'Nome',
      ),
    ),
    new Container(
      padding: new EdgeInsets.all(20.0),
    ),
    new TextFormField(
      decoration: new InputDecoration(
        labelText: 'Data de nascimento',
      ),
    ),
    new Container(
      padding: new EdgeInsets.all(20.0),
    ),
    new Row(
      children: _contatos,
    ),
    new FlatButton(
      onPressed: _addNewContactRow,
      child: new Icon(Icons.add),
    ),
    //new ContactRow()
  ];
Run Code Online (Sandbox Code Playgroud)

现在,这是您到目前为止的专栏。您现在想做的是,看着您的问题,就是为每个联系人添加一个“联系人”行_count

所以我们做简单的老同学迭代,并为每个迭代我们添加一个ContactRow到我们的List

  for (var i = 0; i < _count; ++i) {
    extractedChildren.add(ContactRow());
  }
Run Code Online (Sandbox Code Playgroud)

构造完列表后,将其作为参数传递给子级。

 return new Center(
    child: new Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: extractedChildren,
    ),
  );
Run Code Online (Sandbox Code Playgroud)

这只是一个简单的例子。记住,所有UI都是用纯代码构建的,您可以将代码构建中的所有知识应用到其中。例如,我们可以提取该方法来构建Column的子代以使其更漂亮

    child: new Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: createChildren(),
    ),
Run Code Online (Sandbox Code Playgroud)

现在,我们将创建将返回List iself的新方法,而不是在builder方法内部创建List

List<Widget> createChildren(){
//same code for creating the list
}
Run Code Online (Sandbox Code Playgroud)

重要的事情不要忘记,但是您的代码中已经包含了该_count属性,它是更新内部的属性,setState以便使用新的_count重建子级