Flutter - 单击添加新的小部件
Flutter - Add new Widget on click
我是 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 部分,但我无法让它工作。
有人可以帮忙吗?
这是一种方法
首先,让我们看看什么是children
属性列。
List<Widget> children: const <Widget> []
它是一个 List
的小部件。由于 Flutter UI 是在代码中构建的,因此我们可以传递一个我们之前构造的 children 的数组。无需每次都在 []
中声明它,当您想要在 Column
或 Row
中动态 children 时,这会派上用场
在您的构建器中,您 return Center
包装列的小部件。由于 builder 是一个函数,我们可以在 returning 我们的 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 后,将其作为参数传递给 children。
return new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: extractedChildren,
),
);
这只是一个简单的例子。 Remember All UI 是用纯代码构建的,您可以将代码构建中的所有知识应用于它。例如,
我们可以提取构建 Column children 的方法,使其更漂亮
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: createChildren(),
),
现在,我们将创建新方法,而不是在构建器方法中创建我们的列表,return 列表本身
List<Widget> createChildren(){
//same code for creating the list
}
重要的事情不要忘记,但你的代码中已经有了,就是更新 setState
中的 _count
属性 以便 children 得到重建新_count
只需将 Row 替换为 ListView。
也对 Height/width 进行了一些更改,请查看。
结果:
代码:
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;
});
}
}
我是 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 部分,但我无法让它工作。
有人可以帮忙吗?
这是一种方法
首先,让我们看看什么是children
属性列。
List<Widget> children: const <Widget> []
它是一个 List
的小部件。由于 Flutter UI 是在代码中构建的,因此我们可以传递一个我们之前构造的 children 的数组。无需每次都在 []
中声明它,当您想要在 Column
或 Row
在您的构建器中,您 return Center
包装列的小部件。由于 builder 是一个函数,我们可以在 returning 我们的 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 后,将其作为参数传递给 children。
return new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: extractedChildren,
),
);
这只是一个简单的例子。 Remember All UI 是用纯代码构建的,您可以将代码构建中的所有知识应用于它。例如, 我们可以提取构建 Column children 的方法,使其更漂亮
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: createChildren(),
),
现在,我们将创建新方法,而不是在构建器方法中创建我们的列表,return 列表本身
List<Widget> createChildren(){
//same code for creating the list
}
重要的事情不要忘记,但你的代码中已经有了,就是更新 setState
中的 _count
属性 以便 children 得到重建新_count
只需将 Row 替换为 ListView。
也对 Height/width 进行了一些更改,请查看。
结果:
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;
});
}
}