退出 showModalBottomSheet 并再次显示 showModalBottomSheet 时,Flutter 无法保留状态
Flutter can't preserve stateful state when exit showModalBottomSheet and show showModalBottomSheet again
所以我有下面的代码来显示ModalBottomSheet,并在页面上显示filters/checkboxes。如果我退出模式并再次显示 showModalBottomSheet,那么我看不到复选框值被保留。
好像是第2次显示modal,又调用了_CheckboxStatefulWidgetState的build(),然后默认checkValue为null。
这里是filter.dart
import 'package:flutter/material.dart';
import '../helper/checkbox.dart';
mixin ListFilter<T extends StatefulWidget> on State<T> {
dynamic filters = [
{
"name": "name1",
"choices": [
{'label': 'label1', 'value': 'value1', 'check': false},
{'label': 'label2', 'value': 'value2', 'check': false},
],
},
{
"name": "nameA",
"choices": [
{'label': 'labelA', 'value': 'valueA', 'check': false},
{'label': 'labelB', 'value': 'valueB', 'check': false},
],
},
];
dynamic filterWidgets;
void showFilterModal(context, dynamic filters) {
showModalBottomSheet<void>(
context: context,
//isScrollControlled: true,
builder: (BuildContext context) {
if (filterWidgets == null) {
print("----> filterWidgets is null");
filterWidgets = _getFilterWidgets(filters);
}
return Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: filterWidgets),
),
);
},
);
}
List<Widget> _getFilterWidgets(dynamic filters) {
List<Widget> children = [];
for (var i = 0; i < filters.length; i++) {
dynamic filter = filters[i];
dynamic choices = filter['choices'];
for (var j = 0; j < choices.length; j++) {
dynamic choice = choices[i];
children.add(CheckboxStatefulWidget(
label: choice['label']));
}
Widget divider = Divider();
children.add(divider);
}
return children;
}
}
这里是checkbox.dart
import 'package:flutter/material.dart';
class CheckboxStatefulWidget extends StatefulWidget {
final String label;
CheckboxStatefulWidget({Key key, this.label}) : super(key: key);
@override
_CheckboxStatefulWidgetState createState() =>
_CheckboxStatefulWidgetState();
}
class _CheckboxStatefulWidgetState extends State<CheckboxStatefulWidget> {
bool checkValue;
@override
Widget build(BuildContext context) {
print("checkValue: $checkValue");
print(checkValue == true ?? false);
return CheckboxListTile(
title: Text(this.widget.label),
value: checkValue == true ?? false,
onChanged: (bool newValue) {
setState(() {
checkValue = newValue;
});
});
}
}
我想你可以试试这个解决方案:
- 定义一个变量来存储当前的过滤器选项。
- 当用户提交选项过滤器时 -> 让该过滤器弹出。
- 注意:模态框会在你2号展示的时候重新创建。因此,您需要将该选项弹出到父小部件以进行存储。
FilterModel currentFilterOptions;
Future<FilterModel> showFilterModal(context, FilterModel filters) {
//Show modal
}
...
showFilterModal(context, currentFilterOptions).then((value) {
currentFilterOptions = value;
//DO STH
});
所以我有下面的代码来显示ModalBottomSheet,并在页面上显示filters/checkboxes。如果我退出模式并再次显示 showModalBottomSheet,那么我看不到复选框值被保留。
好像是第2次显示modal,又调用了_CheckboxStatefulWidgetState的build(),然后默认checkValue为null。
这里是filter.dart
import 'package:flutter/material.dart';
import '../helper/checkbox.dart';
mixin ListFilter<T extends StatefulWidget> on State<T> {
dynamic filters = [
{
"name": "name1",
"choices": [
{'label': 'label1', 'value': 'value1', 'check': false},
{'label': 'label2', 'value': 'value2', 'check': false},
],
},
{
"name": "nameA",
"choices": [
{'label': 'labelA', 'value': 'valueA', 'check': false},
{'label': 'labelB', 'value': 'valueB', 'check': false},
],
},
];
dynamic filterWidgets;
void showFilterModal(context, dynamic filters) {
showModalBottomSheet<void>(
context: context,
//isScrollControlled: true,
builder: (BuildContext context) {
if (filterWidgets == null) {
print("----> filterWidgets is null");
filterWidgets = _getFilterWidgets(filters);
}
return Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: filterWidgets),
),
);
},
);
}
List<Widget> _getFilterWidgets(dynamic filters) {
List<Widget> children = [];
for (var i = 0; i < filters.length; i++) {
dynamic filter = filters[i];
dynamic choices = filter['choices'];
for (var j = 0; j < choices.length; j++) {
dynamic choice = choices[i];
children.add(CheckboxStatefulWidget(
label: choice['label']));
}
Widget divider = Divider();
children.add(divider);
}
return children;
}
}
这里是checkbox.dart
import 'package:flutter/material.dart';
class CheckboxStatefulWidget extends StatefulWidget {
final String label;
CheckboxStatefulWidget({Key key, this.label}) : super(key: key);
@override
_CheckboxStatefulWidgetState createState() =>
_CheckboxStatefulWidgetState();
}
class _CheckboxStatefulWidgetState extends State<CheckboxStatefulWidget> {
bool checkValue;
@override
Widget build(BuildContext context) {
print("checkValue: $checkValue");
print(checkValue == true ?? false);
return CheckboxListTile(
title: Text(this.widget.label),
value: checkValue == true ?? false,
onChanged: (bool newValue) {
setState(() {
checkValue = newValue;
});
});
}
}
我想你可以试试这个解决方案:
- 定义一个变量来存储当前的过滤器选项。
- 当用户提交选项过滤器时 -> 让该过滤器弹出。
- 注意:模态框会在你2号展示的时候重新创建。因此,您需要将该选项弹出到父小部件以进行存储。
FilterModel currentFilterOptions;
Future<FilterModel> showFilterModal(context, FilterModel filters) {
//Show modal
}
...
showFilterModal(context, currentFilterOptions).then((value) {
currentFilterOptions = value;
//DO STH
});