【发布时间】:2022-11-15 21:20:12
【问题描述】:
我正在尝试在 ListView 中使用 ListTile 小部件,该小部件将根据应用程序中其他地方收到的一些信息而改变。为了练习,我试着做了一个 Dartpad 的小例子。
问题如下:我已经能够更改项目背后的布尔值和数据,但它们不会在 ListView.builder 中更新。
我在 ListView 中有 ListTile 小部件,我希望有如下四种不同的状态:idle、wait、requested 和 speaking。
我正在尝试更改其中一项的单个状态,但我无法让它们在 ListView 中正确更新。
ListTile 代码如下所示。大部分代码只负责处理每个状态的 UI 应该是什么样子:
class UserItem extends StatefulWidget {
String name;
UserTileState userTileState;
UserItem(this.name, this.userTileState);
@override
UserItemState createState() => UserItemState();
}
class UserItemState extends State<UserItem> {
String _getCorrectTextState(UserTileState userTileState) {
switch (userTileState) {
case UserTileState.speaking:
return "Currently Speaking";
case UserTileState.requested:
return "Speak Request";
case UserTileState.wait:
return "Wait - Someone Speaking";
case UserTileState.idle:
return "Idle";
}
}
Widget _getCorrectTrailingWidget(UserTileState userTileState) {
switch (userTileState) {
case UserTileState.speaking:
return const CircleAvatar(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
child: Icon(Icons.volume_up));
case UserTileState.requested:
return CircleAvatar(
backgroundColor: Colors.green.shade100,
foregroundColor: Colors.grey[700],
child: const Icon(Icons.volume_up),
);
case UserTileState.wait:
return CircleAvatar(
backgroundColor: Colors.green.shade100,
foregroundColor: Colors.grey[700],
child: const Icon(Icons.volume_off),
);
case UserTileState.idle:
return CircleAvatar(
backgroundColor: Colors.green.shade100,
foregroundColor: Colors.grey[700],
child: const Icon(Icons.volume_off),
);
}
}
void kickUser(String name) {
print("Kick $name");
}
@override
Widget build(BuildContext context) {
return ListTile(
onLongPress: () {
kickUser(widget.name);
},
title: Text(widget.name,
style: TextStyle(
fontWeight: widget.userTileState == UserTileState.speaking ||
widget.userTileState == UserTileState.requested
? FontWeight.bold
: FontWeight.normal)),
subtitle: Text(_getCorrectTextState(widget.userTileState),
style: const TextStyle(fontStyle: FontStyle.italic)),
trailing: _getCorrectTrailingWidget(widget.userTileState));
}
}
enum UserTileState { speaking, requested, idle, wait }
为了尝试触发这些UserTile 项目之一的更改,我编写了如下函数。这应该使idle 磁贴成为requested 磁贴。
void userRequest(String name) {
// send a speak request to a tile
int index = users.indexWhere((element) => element.name == name);
users[index].userTileState = UserTileState.requested;
}
然后,我将在按钮内的主构建函数中运行 userRequest,如下所示:
class MyApp extends StatefulWidget {
@override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
void userRequest(String name) {
// send a speak request to a tile
int index = users.indexWhere((element) => element.name == name);
users[index].userTileState = UserTileState.requested;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
Expanded(
flex: 8,
child: ListView.separated(
separatorBuilder: (context, index) {
return const Divider();
},
itemCount: users.length,
itemBuilder: (context, index) {
return users[index];
})),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton(
onPressed: () {
setState(() {
userRequest("Test1");
});
},
child: const Text("Send Request")),
]))
]));
}
}
当我点击按钮在第一个 UserTile 中设置值时,什么也没有发生。
我不知道在哪里放置 setState,并且 ListView 中对象的状态没有被更新。这个问题最简单的解决方案是什么?提供者?我在同样的情况下使用了 Provider 并且无法让它工作。还有另一种更简单的解决方案吗?
如何更改更新 ListView 中特定元素的状态?
【问题讨论】: