提问人:Alec Stanley 提问时间:10/4/2023 最后编辑:Alec Stanley 更新时间:10/5/2023 访问量:20
Flutter 提供程序无法与动态构建的 ExpansionPanelRadio 一起使用
Flutter provider not working with dynamically built ExpansionPanelRadio
问:
我正在构建一个应用程序,其中 ExpansionPanelList 是从自定义类动态构建的。该列表位于标题下方,其中包含有关列表内容的一些详细信息,包括项目总数。
当使用每个单选面板上的尾部按钮从列表中删除项目时,项目将从列表中删除,但标题中显示的总数不会更改(除非用户更改页面并再次返回,从而强制重新生成)。提供程序在封装静态构建的小部件时似乎工作得很好,但这个动态小部件给它带来了问题。我最初使用无状态小部件,但这样做意味着每个面板上的滑块不会更新,列表也不会重新构建,直到采取一些措施来强制它。
我更改为无状态,解决了该问题,但标题未刷新仍然存在。
编辑:这里有一个小总结:
Consumer+builder
->Tab
-> Header,
-> Builder[ExpandingPanels…]
->Drawer
我有消费者的根源,一直尝试到树下,但没有效果。Child 属性设置为“_”,以便它不会忽略 children。
在标题和每个展开面板上,我都添加了一个删除按钮,用于从生成展开面板的列表中删除一个项目。
在抽屉上,我添加了一个按钮,用于将项目添加到列表中。
当按下删除(在页眉和面板上)或添加(在抽屉上)时,结果如下:
- 无状态/有状态标头 - >列表重建、标头更新(即全部按预期工作)
- 有状态列表 -> 列表重新生成,标头不更新
- 有状态抽屉>既不更新列表也不更新标头
所以看起来兄弟姐妹正在和每个人说话
这是标头代码,您可以看到 2 个使用者(除非来回移动到此页面,否则它们不会更新。
class BagHeaderBar extends StatelessWidget {
const BagHeaderBar({
Key? key,
required this.bagIndex,
}) : super(key: key);
final int bagIndex;
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
child: IntrinsicHeight(
child: Row(
children: <Widget>[
Expanded(
flex: 8,
child: Align(
alignment: Alignment.centerLeft,
child: Consumer<PlayerCharacter>( // <--------- this doesn't seem to 'consume'
builder: (context, player, _) {
return Text(
player.bag[bagIndex].bagNotes,
);
}),
)),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.centerRight,
child: Consumer<PlayerCharacter>( // <--------- this doesn't seem to 'consume'
builder: (context, player, _) {
return Text(
'${player.bag[bagIndex].capacityUsed} / ${player.bag[bagIndex].capacityMax}',
style: const TextStyle(fontSize: 18),
);
}),
),
),
],
),
),
));
}
}
这是动态构建的代码,它有删除按钮。它们旨在从列表中删除项目并调整标题中的数字。该项目将被删除(因为它现在是有状态的。它在无状态时不会刷新,但数据已从对象中删除。
class ExpansionInventoryBag extends StatefulWidget {
const ExpansionInventoryBag({
Key? key,
required this.bagIndex,
}) : super(key: key);
final int bagIndex;
@override
State<ExpansionInventoryBag> createState() => _ExpansionInventoryBagState();
}
//---------------------------------------------
class _ExpansionInventoryBagState extends State<ExpansionInventoryBag> {
@override
Widget build(BuildContext context) {
final player = context.read<PlayerCharacter>();
return SingleChildScrollView(
child: ExpansionPanelList.radio(
children: player.bag[widget.bagIndex].contents!.map<ExpansionPanelRadio>((BagSlot bagSlot) {
return ExpansionPanelRadio(
canTapOnHeader: true,
value: bagSlot.slotId,
headerBuilder: (BuildContext context, bool isExpanded) {
return ListTile(
title: Text(
'${bagSlot.getBaseInventoryItem().name} ${(bagSlot.quantity > 1) ? "(${bagSlot.quantity})" : ""}'),
trailing: bagSlot.getBaseInventoryItem().equippable
? Switch(
value: bagSlot.equipped,
onChanged: (bool value) {
final player = context.read<PlayerCharacter>();
setState(() {
player.bag[widget.bagIndex]
.setEquipStateById(bagSlot.slotId, value);
});
},
)
: null,
);
},
body: ListTile(
title: Text(bagSlot.getBaseInventoryItem().shortDescription),
subtitle: Text(bagSlot.slotId),
trailing: const Icon(Icons.delete),
onTap: () {
setState(() {
player.bag[widget.bagIndex].removeItemById(bagSlot.slotId);
});
//final player = context.read<PlayerCharacter>();
},
));
}).toList(),
),
);
}
}
我尝试动态生成 ChangeNotiferProviders,为 BagSlot(构成面板的元素)生成多个提供程序。无状态和有状态小部件。回调。
答: 暂无答案
评论