如何遍历地图列表并在颤振列表视图中显示文本小部件?
How to iterate through list of map and display Text widget in flutter listview?
我是 flutter 的新手 我试图通过内容列表中的 for 循环显示列表视图,但我能够打印一个列表行,这是一次迭代,因为 return 只触发一次。如何遍历完整列表并显示所有listview元素?
下面是地图内容列表
List<Map<String, String>> users = [
{"name": "Staff 1", "status": "Online"},
{"name": "Staff 2", "status": "Online"},
{"name": "Staff 3", "status": "Offline"},
{"name": "Vehicle 1", "status": "Available"},
{"name": "Vehicle 2", "status": "Unavailable"},
{"name": "Team 1", "status": "Active"},
{"name": "Team 2", "status": "Not Active"},
];
下面是我要显示的列表视图小部件的代码
Widget ListViewBuilder() {
for (var i = 0; i < users.length; i++) {
print(i);
return Expanded(
child: ListView(
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: AssetImage("assets/profileavatar.png")),
title: Text(users[i]['name']),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
users[i]['status'],
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
],
),
);
}
}
这将只显示列表中的第一个元素,如何实现显示列表用户中存在的所有列表视图元素?任何建议都会有所帮助
这里的问题是 - 您在第一个循环中 return 计算结果。这就是为什么你只得到列表中的第一个元素。
您需要在 ListView 小部件中循环访问您的地图。
List<Map<String, String>> users = [
{"name": "Staff 1", "status": "Online"},
{"name": "Staff 2", "status": "Online"},
{"name": "Staff 3", "status": "Offline"},
{"name": "Vehicle 1", "status": "Available"},
{"name": "Vehicle 2", "status": "Unavailable"},
{"name": "Team 1", "status": "Active"},
{"name": "Team 2", "status": "Not Active"},
];
Widget ListViewBuilder(BuildContext context) {
return Expanded(
child: ListView(
children: <Widget>[
...users.map( (u) =>
<Widget> [GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: AssetImage("assets/profileavatar.png")),
title: Text(u['name']),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
u['status'],
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
SizedBox(
width: 20,
),
InkWell(
onTap: () {
Navigator.pushNamed(
context,
'/viewlocation',
);
},
child: Icon(
Icons.add_location,
color: Colors.green,
size: 40,
),
),
SizedBox(
width: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
color: Colors.green,
),
borderRadius:
BorderRadius.all(Radius.circular(20))),
child: InkWell(
onTap: () async {
const number =
'08592119XXXX'; //set the number here
bool res =
await FlutterPhoneDirectCaller.callNumber(
number);
},
child: Icon(
Icons.call,
color: Colors.white,
size: 40,
),
),
)
])),
),
Divider(
color: Colors.black,
endIndent: 10,
indent: 10,
)
]).expand((element) => element).toList()
,
],
),
);
}
这里发生的事情很少:
users.map() 将 运行 为列表的每个元素提供功能。
由于您要创建两个元素的迷你列表 - GestureDetector 和 Divider,该函数将 return 小部件列表
您的地图函数的结果将是 [[GestureDetector, Divider], [GestureDetector, Divider],...]。这就是为什么我们 运行 展开以使其扁平化 (https://api.dart.dev/stable/2.10.5/dart-core/Iterable/expand.html)
最后,使用扩展运算符 (...) (...users.map( (u) =>) 将元素卸载到包含列表中。因此:
child: ListView(
children: <Widget>[
[GestureDetector, Divider, GestureDetector, Divider]]
变成
child: ListView(
children: <Widget>[
GestureDetector, Divider, GestureDetector, Divider]
问题是您在每个循环中构建 ListView
。您可以使用循环构建一个 ListTile
列表并传递给 ListView
但我建议您使用 ListView.separated
,它更容易。喜欢
Widget listViewBuilder() {
return Expanded(
child: ListView.separated(
itemCount: users.length,
itemBuilder: (context, i) {
return GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage:
AssetImage("assets/profileavatar.png")),
title: Text(users[i]['name']),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
users[i]['status'],
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
SizedBox(
width: 20,
),
InkWell(
onTap: () {
Navigator.pushNamed(
context,
'/viewlocation',
);
},
child: Icon(
Icons.add_location,
color: Colors.green,
size: 40,
),
),
SizedBox(
width: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
color: Colors.green,
),
borderRadius:
BorderRadius.all(Radius.circular(20))),
child: InkWell(
onTap: () async {
const number =
'08592119XXXX'; //set the number here
bool res =
await FlutterPhoneDirectCaller.callNumber(
number);
},
child: Icon(
Icons.call,
color: Colors.white,
size: 40,
),
),
)
])),
);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: Colors.black,
endIndent: 10,
indent: 10,
);
}));
}
编辑:我在你那里的分隔线上隔开,我同意@Sam Chan 的建议 ListView.separated
而不是我之前建议的 ListView.builder
。
对于初学者来说,将 ListTile
提取到它自己的小部件并传入几个字符串会更清晰。否则它会很快变得混乱。这是一个例子。
class CustomListTile extends StatelessWidget {
final String name, status;
const CustomListTile({Key key, this.name, this.status}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: AssetImage("assets/profileavatar.png")),
title: Text(name),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
status,
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
SizedBox(
width: 20,
),
InkWell(
onTap: () {
Navigator.pushNamed(
context,
'/viewlocation',
);
},
child: Icon(
Icons.add_location,
color: Colors.green,
size: 40,
),
),
SizedBox(
width: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
color: Colors.green,
),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: InkWell(
onTap: () async {
const number = '08592119XXXX'; //set the number here
// bool res = await FlutterPhoneDirectCaller.callNumber(number);
},
child: Icon(
Icons.call,
color: Colors.white,
size: 40,
),
),
)
],
),
),
);
}
}
这是显示地图列表的完整页面示例。
class DemoPage extends StatelessWidget {
DemoPage({
Key key,
}) : super(key: key);
final List<Map<String, String>> users = [
{"name": "Staff 1", "status": "Online"},
{"name": "Staff 2", "status": "Online"},
{"name": "Staff 3", "status": "Offline"},
{"name": "Vehicle 1", "status": "Available"},
{"name": "Vehicle 2", "status": "Unavailable"},
{"name": "Team 1", "status": "Active"},
{"name": "Team 2", "status": "Not Active"},
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ListView.separated(
separatorBuilder: (BuildContext context, int index) => Divider(
color: Colors.black,
endIndent: 10,
indent: 10,
),
itemCount: users.length,
itemBuilder: (context, index) {
// parsing the maps in the list before passing them into the extracted widget
// the itemBuilder iterates through the list
final name = users[index]['name'];
final status = users[index]['status'];
return CustomListTile(name: name, status: status);
},
),
),
],
),
);
}
}
我是 flutter 的新手 我试图通过内容列表中的 for 循环显示列表视图,但我能够打印一个列表行,这是一次迭代,因为 return 只触发一次。如何遍历完整列表并显示所有listview元素? 下面是地图内容列表
List<Map<String, String>> users = [
{"name": "Staff 1", "status": "Online"},
{"name": "Staff 2", "status": "Online"},
{"name": "Staff 3", "status": "Offline"},
{"name": "Vehicle 1", "status": "Available"},
{"name": "Vehicle 2", "status": "Unavailable"},
{"name": "Team 1", "status": "Active"},
{"name": "Team 2", "status": "Not Active"},
];
下面是我要显示的列表视图小部件的代码
Widget ListViewBuilder() {
for (var i = 0; i < users.length; i++) {
print(i);
return Expanded(
child: ListView(
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: AssetImage("assets/profileavatar.png")),
title: Text(users[i]['name']),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
users[i]['status'],
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
],
),
);
}
}
这将只显示列表中的第一个元素,如何实现显示列表用户中存在的所有列表视图元素?任何建议都会有所帮助
这里的问题是 - 您在第一个循环中 return 计算结果。这就是为什么你只得到列表中的第一个元素。
您需要在 ListView 小部件中循环访问您的地图。
List<Map<String, String>> users = [
{"name": "Staff 1", "status": "Online"},
{"name": "Staff 2", "status": "Online"},
{"name": "Staff 3", "status": "Offline"},
{"name": "Vehicle 1", "status": "Available"},
{"name": "Vehicle 2", "status": "Unavailable"},
{"name": "Team 1", "status": "Active"},
{"name": "Team 2", "status": "Not Active"},
];
Widget ListViewBuilder(BuildContext context) {
return Expanded(
child: ListView(
children: <Widget>[
...users.map( (u) =>
<Widget> [GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: AssetImage("assets/profileavatar.png")),
title: Text(u['name']),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
u['status'],
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
SizedBox(
width: 20,
),
InkWell(
onTap: () {
Navigator.pushNamed(
context,
'/viewlocation',
);
},
child: Icon(
Icons.add_location,
color: Colors.green,
size: 40,
),
),
SizedBox(
width: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
color: Colors.green,
),
borderRadius:
BorderRadius.all(Radius.circular(20))),
child: InkWell(
onTap: () async {
const number =
'08592119XXXX'; //set the number here
bool res =
await FlutterPhoneDirectCaller.callNumber(
number);
},
child: Icon(
Icons.call,
color: Colors.white,
size: 40,
),
),
)
])),
),
Divider(
color: Colors.black,
endIndent: 10,
indent: 10,
)
]).expand((element) => element).toList()
,
],
),
);
}
这里发生的事情很少:
users.map() 将 运行 为列表的每个元素提供功能。
由于您要创建两个元素的迷你列表 - GestureDetector 和 Divider,该函数将 return 小部件列表
您的地图函数的结果将是 [[GestureDetector, Divider], [GestureDetector, Divider],...]。这就是为什么我们 运行 展开以使其扁平化 (https://api.dart.dev/stable/2.10.5/dart-core/Iterable/expand.html)
最后,使用扩展运算符 (...) (...users.map( (u) =>) 将元素卸载到包含列表中。因此:
child: ListView(
children: <Widget>[
[GestureDetector, Divider, GestureDetector, Divider]]
变成
child: ListView(
children: <Widget>[
GestureDetector, Divider, GestureDetector, Divider]
问题是您在每个循环中构建 ListView
。您可以使用循环构建一个 ListTile
列表并传递给 ListView
但我建议您使用 ListView.separated
,它更容易。喜欢
Widget listViewBuilder() {
return Expanded(
child: ListView.separated(
itemCount: users.length,
itemBuilder: (context, i) {
return GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage:
AssetImage("assets/profileavatar.png")),
title: Text(users[i]['name']),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
users[i]['status'],
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
SizedBox(
width: 20,
),
InkWell(
onTap: () {
Navigator.pushNamed(
context,
'/viewlocation',
);
},
child: Icon(
Icons.add_location,
color: Colors.green,
size: 40,
),
),
SizedBox(
width: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
color: Colors.green,
),
borderRadius:
BorderRadius.all(Radius.circular(20))),
child: InkWell(
onTap: () async {
const number =
'08592119XXXX'; //set the number here
bool res =
await FlutterPhoneDirectCaller.callNumber(
number);
},
child: Icon(
Icons.call,
color: Colors.white,
size: 40,
),
),
)
])),
);
},
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: Colors.black,
endIndent: 10,
indent: 10,
);
}));
}
编辑:我在你那里的分隔线上隔开,我同意@Sam Chan 的建议 ListView.separated
而不是我之前建议的 ListView.builder
。
对于初学者来说,将 ListTile
提取到它自己的小部件并传入几个字符串会更清晰。否则它会很快变得混乱。这是一个例子。
class CustomListTile extends StatelessWidget {
final String name, status;
const CustomListTile({Key key, this.name, this.status}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.pushNamed(
context,
'/chatscreen',
);
},
child: ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: AssetImage("assets/profileavatar.png")),
title: Text(name),
subtitle: Text("User -ID"),
trailing: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // added line
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
status,
style: TextStyle(
color: Colors.green,
fontSize: 20,
),
),
SizedBox(
width: 20,
),
InkWell(
onTap: () {
Navigator.pushNamed(
context,
'/viewlocation',
);
},
child: Icon(
Icons.add_location,
color: Colors.green,
size: 40,
),
),
SizedBox(
width: 20,
),
Container(
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(
color: Colors.green,
),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: InkWell(
onTap: () async {
const number = '08592119XXXX'; //set the number here
// bool res = await FlutterPhoneDirectCaller.callNumber(number);
},
child: Icon(
Icons.call,
color: Colors.white,
size: 40,
),
),
)
],
),
),
);
}
}
这是显示地图列表的完整页面示例。
class DemoPage extends StatelessWidget {
DemoPage({
Key key,
}) : super(key: key);
final List<Map<String, String>> users = [
{"name": "Staff 1", "status": "Online"},
{"name": "Staff 2", "status": "Online"},
{"name": "Staff 3", "status": "Offline"},
{"name": "Vehicle 1", "status": "Available"},
{"name": "Vehicle 2", "status": "Unavailable"},
{"name": "Team 1", "status": "Active"},
{"name": "Team 2", "status": "Not Active"},
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ListView.separated(
separatorBuilder: (BuildContext context, int index) => Divider(
color: Colors.black,
endIndent: 10,
indent: 10,
),
itemCount: users.length,
itemBuilder: (context, index) {
// parsing the maps in the list before passing them into the extracted widget
// the itemBuilder iterates through the list
final name = users[index]['name'];
final status = users[index]['status'];
return CustomListTile(name: name, status: status);
},
),
),
],
),
);
}
}