AddPatientView というページがあり、BottomNavigationBar には AddPatientInfo ページと AddPatientImages ページが含まれています。これら 3 つはすべてステートフル ウィジェットです。
デフォルトでは、一連のテキストフィールド (患者情報を入力) を含む AddPatientInfo が開き、AddPatientImages ページでユーザーは画像を追加できます。
問題は、AddPatientInfo の TextFields に入力してから AddPatientImages に移動して戻ると、すべての TextFields が空になることです。ウィジェット ツリー全体が再構築され、入力したデータがすべて失われるため、当然のことです。
そこで、タブが変更されても状態が維持されるように実装しています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: _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;
});
},
),
);
}
}
患者情報の追加
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;
}
ここで何が欠けているのでしょうか? フォーム内のデータを維持するよりエレガントな方法はありますか?
ベストアンサー1
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;
});
},
),
);
}
}