我正在嘗試在 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")),
]))
]));
}
}
當我點擊按鈕在 first 中設定值UserTile時,什么也沒有發生。
我不知道在哪里放置 setState,并且 ListView 中物件的狀態沒有被更新。這個問題最簡單的解決方案是什么?提供者?我在同樣的情況下使用了 Provider 并且無法讓它作業。還有另一種更簡單的解決方案嗎?
如何更改更新 ListView 中特定元素的狀態?
uj5u.com熱心網友回復:
我相信問題出在_getCorrectTextState()
創建一個變數,String _status;
然后做這樣的事情;
void _getCorrectTextState(UserTileState userTileState) {
String tmpState;
switch (userTileState) {
case UserTileState.speaking:
tmpState = "Currently Speaking";
case UserTileState.requested:
tmpState = "Speak Request";
case UserTileState.wait:
tmpState = "Wait - Someone Speaking";
case UserTileState.idle:
tmpState = "Idle";
}
setState(() => {_state = tmpState});
}
然后在您的構建中:
subtitle: _state;
uj5u.com熱心網友回復:
您可以使用 StatefulBuilder() - 通過使用它,您將為串列中的每個專案獲得一個單獨的狀態,可以更新
像這樣:
ListView.separated(
separatorBuilder: (context, index) {
return const Divider();
},
itemCount: users.length,
itemBuilder: (context, index) {
return StatefulBuilder(
builder: ((context, setStateItem){
//return_your_listTile_widget_here
//use setStateItem (as setState) this will update the state of selected item
setStateItem(() {
//code for update the listView item
});
})
);
})),

uj5u.com熱心網友回復:
我發布的代碼對某些人來說結果好壞參半。我的主要專案實際上有點復雜并且涉及Provider,但是當我發布這個問題時,我盡力將代碼剝離到最簡單的部分。我想知道是否有其他東西阻礙了這項作業。(也許是因為我用 dartpad 把這個例子放在一起?)
同時,我發現在串列中添加或洗掉元素似乎會改變串列的整個狀態。使用這種技術,我沒有嘗試更改單個值,而是獲取它的索引,洗掉它,然后在該索引處重新添加它,它就像一個魅力。所以代替這個:
void userRequest(String name) {
// send a speak request to a tile
int index = users.indexWhere((element) => element.name == name);
users[index].userTileState = UserTileState.requested;
}
其次是setState(() => userRequest("name");,以下似乎可以代替:
void userRequest(String name) {
// send a speak request to a tile
int index = users.indexWhere((element) => element.name == name);
users.removeAt(index);
users.insert(index, UserItem(name, UserTileStates.requested));
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/531711.html
標籤:扑列表显示列表瓦片
