如何在活动时从父级更新 ModalBottomSheet 的内容
How to update content of a ModalBottomSheet from parent while active
我有一个接受项目列表的自定义按钮。按下时,它会打开一个模态底部 sheet 并将该列表传递给底部 sheet.
但是,当按钮项目发生变化时,它不会更新底部的项目 sheet。
如何实现这种效果。
简单示例
ButtonsPage
|
Button(items: initialItems)
|
BottomSheet(items: initialItems)
** After a delay, setState is called in ButtonsPage with newItems, thereby sending newItems to the button
ButtonsPage
|
Button(items: newItems)
| ## Here, the bottom sheet is open. I want it to update initialItems to be newItems in the bottom sheet
BottomSheet(items: initialItems -- should be newItems)
代码示例
这是我的 select 字段,如图所示,它接收一个列表 items
并且当它被按下时它打开一个底部 sheet 并将收到的项目发送到底部 sheet.
class PaperSelect extends StatefulWidget {
final List<dynamic> items;
PaperSelect({
this.items,
}) : super(key: key);
@override
_PaperSelectState createState() => _PaperSelectState();
}
class _PaperSelectState extends State<PaperSelect> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.disabled ? null : () => _showBottomSheet(context),
child: Container(
),
);
}
void _showBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (BuildContext context) => BottomSheet(
items: widget.items,
),
)
);
}
}
一段时间后(一次网络调用),items
在 PaperSelect
的父 Widget 中更新。 PaperSelect
然后更新并接收新项目。
class BottomSheet extends StatefulWidget {
final dynamic items;
BottomSheet({
this.items,
}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _BottomSheetState();
}
}
class _BottomSheetState extends State<BottomSheet> {
dynamic items;
@override
void initState() {
print(widget.items);
items = widget.items;
super.initState();
}
@override
Widget build(BuildContext context) {
if(items==null) return Center(
child: SizedBox(
width: 140.0,
height: 140.0,
child: PaperLoader()
),
);
if(items==-1) return Text("Network Error");
return Column(
children: <Widget>
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (BuildContext context, int i) => ListTile(
onTap: () => Navigator.pop(context),
title: Text('')
)
),
),
],
);
}
}
现在,我要将更新后的数据发送到底部sheet。但是,它不起作用,因为 ModalBottomSheet 已经打开。
我该如何解决这个问题?
我在这里假设 items 是 List<String>
,因为您根本没有指定它。 (在大多数情况下,您通常不应使用 dynamic
,因为它根本不进行任何类型检查)。无论如何,
你可以做的一件事(除了无数其他人之外)是传递 ValueNotifier<List<String>>
而不是 List<String>
然后在你的底部使用 ValueListenableBuilder
sheet.喜欢:
// in the caller
final itemsNotifier = ValueNotifier(items);
// in your bottom sheet
ValueListenableBuilder<List<String>>(
valueListenable: itemsNotifier,
builder: (context, snapshot, child) {
final items = snapshot.data;
// build your list
},
)
然后每次您更改 itemsNotifier.value = [...]
您的项目都会重建。
更新itemsNotifier.value
时注意:不能在build
/didUpdateWidget
/等里面完成。因此,如果是这种情况,您可以使用 WidgetsBinding.instance.addPostFrameCallback(() => itemsNotifier.value = ... )
将值更新推迟到当前构建阶段之后。
我有一个接受项目列表的自定义按钮。按下时,它会打开一个模态底部 sheet 并将该列表传递给底部 sheet.
但是,当按钮项目发生变化时,它不会更新底部的项目 sheet。
如何实现这种效果。
简单示例
ButtonsPage
|
Button(items: initialItems)
|
BottomSheet(items: initialItems)
** After a delay, setState is called in ButtonsPage with newItems, thereby sending newItems to the button
ButtonsPage
|
Button(items: newItems)
| ## Here, the bottom sheet is open. I want it to update initialItems to be newItems in the bottom sheet
BottomSheet(items: initialItems -- should be newItems)
代码示例
这是我的 select 字段,如图所示,它接收一个列表 items
并且当它被按下时它打开一个底部 sheet 并将收到的项目发送到底部 sheet.
class PaperSelect extends StatefulWidget {
final List<dynamic> items;
PaperSelect({
this.items,
}) : super(key: key);
@override
_PaperSelectState createState() => _PaperSelectState();
}
class _PaperSelectState extends State<PaperSelect> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.disabled ? null : () => _showBottomSheet(context),
child: Container(
),
);
}
void _showBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (BuildContext context) => BottomSheet(
items: widget.items,
),
)
);
}
}
一段时间后(一次网络调用),items
在 PaperSelect
的父 Widget 中更新。 PaperSelect
然后更新并接收新项目。
class BottomSheet extends StatefulWidget {
final dynamic items;
BottomSheet({
this.items,
}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _BottomSheetState();
}
}
class _BottomSheetState extends State<BottomSheet> {
dynamic items;
@override
void initState() {
print(widget.items);
items = widget.items;
super.initState();
}
@override
Widget build(BuildContext context) {
if(items==null) return Center(
child: SizedBox(
width: 140.0,
height: 140.0,
child: PaperLoader()
),
);
if(items==-1) return Text("Network Error");
return Column(
children: <Widget>
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (BuildContext context, int i) => ListTile(
onTap: () => Navigator.pop(context),
title: Text('')
)
),
),
],
);
}
}
现在,我要将更新后的数据发送到底部sheet。但是,它不起作用,因为 ModalBottomSheet 已经打开。
我该如何解决这个问题?
我在这里假设 items 是 List<String>
,因为您根本没有指定它。 (在大多数情况下,您通常不应使用 dynamic
,因为它根本不进行任何类型检查)。无论如何,
你可以做的一件事(除了无数其他人之外)是传递 ValueNotifier<List<String>>
而不是 List<String>
然后在你的底部使用 ValueListenableBuilder
sheet.喜欢:
// in the caller
final itemsNotifier = ValueNotifier(items);
// in your bottom sheet
ValueListenableBuilder<List<String>>(
valueListenable: itemsNotifier,
builder: (context, snapshot, child) {
final items = snapshot.data;
// build your list
},
)
然后每次您更改 itemsNotifier.value = [...]
您的项目都会重建。
更新itemsNotifier.value
时注意:不能在build
/didUpdateWidget
/等里面完成。因此,如果是这种情况,您可以使用 WidgetsBinding.instance.addPostFrameCallback(() => itemsNotifier.value = ... )
将值更新推迟到当前构建阶段之后。