我有一个名为AddPatientView的页面,其中的BottomNavigationBar包含AddPatientInfo和AddPatientImages页面。这三个都是有状态的小部件。
默认情况下,AddPatientInfo将打开,其中包含一堆TextField(用于输入患者信息),用户可以在AddPatientImages页面中添加图像。
问题是,如果我在AddPatientInfo上填充TextField,然后转到AddPatientImages,然后返回,则所有TextField都是空的。正确地这样,因为整个小部件树都得到了重建,因此我丢失了所有填充的数据。
因此,我正在实现AutomaticKeepAliveClientMixin
,因此即使更改了选项卡,状态也会保持不变。但这似乎不起作用:
这是我的代码:
AddPatientView (父级)
class AddPatientView extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _AddPatientViewState();
}
}
class _AddPatientViewState extends State<AddPatientView> {
int _currentIndex = 0;
List<Widget> _children;
List<File> _imageFileList = new List<File>();
@override
void initState() {
super.initState();
_children = [
AddPatientInfo(savePatient),
AddPatientImages(_imageFileList)
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("New Patient Record"),
),
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(icon: new Icon(Icons.create), title: new Text('Info')),
BottomNavigationBarItem(icon: new Icon(Icons.camera_alt), title: new Text('Images')),
],
onTap: (int index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
AddPatientInfo
class AddPatientInfo extends StatefulWidget {
final Function savePatient;
AddPatientInfo(this.savePatient){
}
@override
State<StatefulWidget> createState() {
return _AddPatientInfoState();
}
}
class _AddPatientInfoState extends State<AddPatientInfo> with AutomaticKeepAliveClientMixin<AddPatientInfo> {
Function _savePatient;
String _firstName, _lastName, _gender, _phone, _email, _diabetesMeds, _hypertensionMeds, _others;
int _age, _diabetesYears, _hypertensionYears, _smokesPerDay, _smokerYears;
bool _diabetes = false, _hypertension = false, _smoker = false, _chestPain = false,
_cva = false, _ckd = false, _breathlessness = false,
_syncope = false, _sweating = false, _sweatingFeet = false;
List<String> _genderList = new List<String>();
List<String> _yesNoList = new List<String>();
List<File> _imageFileList = new List<File>();
@override
void initState() {
super.initState();
_savePatient = widget.savePatient;
_genderList.addAll(['Male', 'Female', 'Other']);
_yesNoList.addAll(['Yes', 'No']);
_gender = _genderList.elementAt(0);
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
body: Container(
margin: EdgeInsets.all(10.0),
child: Form(
child: new ListView(
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: 'Patient First Name',
labelStyle: TextStyle(
color: Colors.black
),
hintText: 'Enter patients first name'
),
onChanged: (String value) {
setState(() {
_firstName = value;
});
},
),
TextField(
decoration: InputDecoration(
labelText: 'Patient Last Name',
labelStyle: TextStyle(
color: Colors.black
),
hintText: 'Enter patients last name'
),
onChanged: (String value) {
setState(() {
_lastName = value;
});
},
),
//other textfield widgets below
],
),
)
),
);
}
@override
bool get wantKeepAlive => true;
}
我在这里想念什么?有没有更优雅的方法来维护表单中的数据?
答案 0 :(得分:9)
如果您希望AutomaticKeepAliveClientMixin继续工作,请使用PageView包裹正文,代码应如下所示
class AddPatientView extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _AddPatientViewState();
}
}
class _AddPatientViewState extends State<AddPatientView> {
int _currentIndex = 0;
List<Widget> _children;
List<File> _imageFileList = new List<File>();
// add
final pageController = PageController();
void onPageChanged(int index) {
setState(() {
_currentIndex = index;
});
}
@override
void initState() {
super.initState();
_children = [AddPatientInfo(savePatient), AddPatientImages(_imageFileList)];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("New Patient Record"),
),
// here!!!
body: PageView(
children: _children,
controller: pageController,
onPageChanged: onPageChanged,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.create), title: new Text('Info')),
BottomNavigationBarItem(
icon: new Icon(Icons.camera_alt), title: new Text('Images')),
],
onTap: (int index) {
// setState(() {
// _currentIndex = index;
// });
// update
pageController.jumpToPage(index);
},
),
);
}
}
但是如果您只是想保持页面状态,建议您使用IndexedStack,它非常简单,不需要AutomaticKeepAliveClientMixin,代码应该是这样
class AddPatientView extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _AddPatientViewState();
}
}
class _AddPatientViewState extends State<AddPatientView> {
int _currentIndex = 0;
List<Widget> _children;
List<File> _imageFileList = new List<File>();
@override
void initState() {
super.initState();
_children = [
AddPatientInfo(savePatient),
AddPatientImages(_imageFileList)
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("New Patient Record"),
),
body: IndexedStack(
index:_currentIndex,
children:_children
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(icon: new Icon(Icons.create), title: new Text('Info')),
BottomNavigationBarItem(icon: new Icon(Icons.camera_alt), title: new Text('Images')),
],
onTap: (int index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
答案 1 :(得分:5)
摘自AutomaticKeepAliveClientMixin上的文档:
/// A mixin with convenience methods for clients of [AutomaticKeepAlive]. Used
/// with [State] subclasses.
///
/// Subclasses must implement [wantKeepAlive], and their [build] methods must
/// call `super.build` (the return value will always return null, and should be
/// ignored).
因此,在您的示例中,在返回脚手架之前,只需调用super.build:
Widget build(BuildContext context) {
super.build(context);
return Scaffold(...);
}
答案 2 :(得分:2)
因此我将选项卡页面包装在Stack小部件中,现在它使表单状态保持不变。我不确定这是否是正确的方法,但确实可以。
代码如下:
AddPatientView (父级)
class AddPatientView extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _AddPatientViewState();
}
}
class _AddPatientViewState extends State<AddPatientView> {
int _currentIndex = 0;
List<File> _imageFileList = new List<File>();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("New Patient Record"),
),
body: new Stack(
children: <Widget>[
new Offstage(
offstage: _currentIndex != 0,
child: AddPatientInfo(savePatient),
),
new Offstage(
offstage: _currentIndex != 1,
child: AddPatientImages(_imageFileList),
)
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: [
BottomNavigationBarItem(icon: new Icon(Icons.create), title: new Text('Info')),
BottomNavigationBarItem(icon: new Icon(Icons.camera_alt), title: new Text('Images')),
],
onTap: (int index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
答案 3 :(得分:0)
AutomaticKeepAliveMixin 通常只用于 pageview/tabview/另一个正在重建的视图,它保留了一个状态,显然不会重建 我们需要控制器