简体   繁体   English

Flutter-单击添加新的小部件

[英]Flutter - Add new Widget on click

I'm new to flutter and I'm trying to build a rather simple app. 我是新手,我正在尝试构建一个相当简单的应用程序。 I have this simple (and still in progress) code and I'm trying to add a new Widget every time the user clicks a button. 我有这个简单的代码(仍在进行中),我试图在用户每次单击按钮时添加一个新的小部件。

Here's my code: 这是我的代码:

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

I want to add another ContactRow when the user clicks that Flat Button with addNewContactRow() on onPressed. 当用户在onPressed上使用addNewContactRow()单击该平面按钮时,我想添加另一个ContactRow。 I've found the code on addNewContactRow() and the List.generate part on another question here, but I can't make it work. 我在addNewContactRow()上找到了代码,在这里的另一个问题上找到了List.generate部分,但是我无法使其正常工作。

Can some one please help? 有人可以帮忙吗?

This is one way to do it 这是做到这一点的一种方法

First, let's see what is children property of a column. 首先,让我们看看列的children属性是什么。

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

It is a List of Widgets. 这是小部件List Since Flutter UI is built in code, we can pass an array of children that we constructed before. 由于Flutter UI是用代码内置的,因此我们可以传递之前构造的子代数组。 No need to declare it in [] every time, and this comes handy when you want dynamic children inside Column or Row 无需每次都在[]声明它,当您希望在ColumnRow动态子级时,这很方便

In your builder, you return Center widget that wraps the column. 在您的构建器中,您返回包裹该列的Center小部件。 since builder is a function, we can do some magic prior to returning our Widget. 由于builder是一个函数,因此我们可以在返回Widget之前做一些魔术。

Let us first extract the array from the Column itself in one variable: 让我们首先从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()
  ];

Now, this was the column that you had so far. 现在,这是您到目前为止的专栏。 What you want to do right now, looking at your question, is to add one Contact row for each _count 您现在想做的是,看看您的问题,就是为每个_count添加一个Contact行

So we do simple old school iteration, and for each iteration we add one ContactRow to our List 因此,我们进行了简单的旧式迭代,对于每次迭代,我们在List添加一个ContactRow

  for (var i = 0; i < _count; ++i) {
    extractedChildren.add(ContactRow());
  }

After we have our List constructed, pass it as an argument to the children. 构造完列表后,将其作为参数传递给子级。

 return new Center(
    child: new Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: extractedChildren,
    ),
  );

This is just a simple example. 这只是一个简单的例子。 Remember All UI is built with pure code and you can apply all your knowledge from code building to it. 记住,所有UI都是用纯代码构建的,您可以将代码构建中的所有知识应用到其中。 For example, we can extract the method to build the children of Column to make it more pretty 例如,我们可以提取该方法来构建Column的子代以使其更漂亮

    child: new Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: createChildren(),
    ),

Now, instead of creating our List inside the builder method, we would create new method that would return the List iself 现在,我们将创建将返回List iself的新方法,而不是在builder方法内部创建List

List<Widget> createChildren(){
//same code for creating the list
}

Important thing not to forget, but you already have that in your code, is to update the _count property inside setState so that children get rebuilt with new _count 重要的事情不要忘记,但是您的代码中已经包含了该内容,它是更新setState内的_count属性,以便使用新的_count重新构造子级

Just replace Row with ListView. 只需用ListView替换Row。

Also made few changes in Height/width check it out. 还对高度/宽度进行了一些更改,将其签出。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM