我是新手,我试图建立一个相当简单的应用程序。 我有这个简单(并且仍在进行中)的代码,每次用户点击按钮时我都会尝试添加新的Widget。
这是我的代码:
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;
});
}
}
当用户在onPressed上点击带有addNewContactRow()的Flat Button时,我想添加另一个ContactRow。 我在addNewContactRow()和List.generate部分找到了另一个问题的代码,但是我无法使其工作。
有人可以帮忙吗?
答案 0 :(得分:5)
这是一种方法
首先,让我们看看列的children
属性是什么。
List<Widget> children: const <Widget> []
这是小部件的List
。由于Flutter UI是用代码构建的,我们可以传递我们之前构建的子数组。无需每次都在[]
声明,当您想要Column
或Row
在构建器中,返回包装列的Center
窗口小部件。因为构建器是一个函数,所以我们可以在返回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()
];
现在,这是你到目前为止的专栏。您现在要查看的问题是,为每个_count
添加一个联系人行
因此我们进行简单的旧学校迭代,并且对于每次迭代,我们将ContactRow
添加到List
for (var i = 0; i < _count; ++i) {
extractedChildren.add(ContactRow());
}
在我们构建了List之后,将它作为参数传递给孩子们。
return new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: extractedChildren,
),
);
这只是一个简单的例子。记住所有UI都是使用纯代码构建的,您可以将所有知识从代码构建应用到它。例如, 我们可以提取方法来构建Column的子级以使其更漂亮
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: createChildren(),
),
现在,我们不是在builder方法中创建List,而是创建一个返回List iself的新方法
List<Widget> createChildren(){
//same code for creating the list
}
重要的是不要忘记,但是您已经在代码中使用了这一点,就是更新_count
内的setState
属性,以便使用新的_count重建子项
答案 1 :(得分:2)
只需用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;
});
}
}