我是 flutter 新手,我正在尝试构建一个相当简单的应用程序。 我有这个简单的(仍在进行中)代码,并且每次用户单击按钮时我都尝试添加一个新的小部件。
这是我的代码:
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() 单击该平面按钮时,我想添加另一个 ContactRow。 我在这里找到了 addNewContactRow() 上的代码和另一个问题上的 List.generate 部分,但我无法使其工作。
有人可以帮忙吗?
只需将 Row 替换为 ListView 即可。
还对高度/宽度做了一些更改,检查一下。
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;
});
}
}
这是一种方法
首先,我们来看看什么是列的
children
属性。
List<Widget> children: const <Widget> []
它是一个
List
小部件。由于 Flutter UI 是在代码中构建的,因此我们可以传递之前构造的子级数组。无需每次都在 []
中声明它,当您想要动态子级在 Column
或 Row
中时,这会很方便
在您的构建器中,您返回包裹该列的
Center
小部件。由于 builder 是一个函数,因此我们可以在返回 Widget 之前做一些魔法。
让我们首先从列本身中提取数组到一个变量中:
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());
}
构建列表后,将其作为参数传递给子级。
return new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: extractedChildren,
),
);
这只是一个简单的例子。请记住,所有 UI 都是用纯代码构建的,您可以将代码构建中的所有知识应用到其中。例如, 我们可以提取构建 Column 子级的方法,使其更漂亮
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: createChildren(),
),
现在,我们将创建返回列表本身的新方法,而不是在构建器方法中创建列表
List<Widget> createChildren(){
//same code for creating the list
}
不要忘记的重要事情是更新
_count
中的 setState
属性,以便子级使用新的 _count 进行重建,但您的代码中已经有了这一点
更新了@Ajay为新的Flutter 3.13.0和Dart 3.1.0提供的代码
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 ElevatedButton(
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 DropdownButtonFormField(
value: _currentContactType,
items: _dropDownMenuItems,
onChanged: changedDropDownItem,
// onChanged: (String changedValue) {
// newValue=changedValue;
// setState(() {
// newValue;
// print(newValue);
// });
// },
),
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 = [];
for (String city in _contactTypes) {
items.add(new DropdownMenuItem(value: city, child: new Text(city)));
}
return items;
}
void changedDropDownItem(String? selectedCity) {
setState(() {
_currentContactType = selectedCity;
});
}
}