I have page called AddPatientView with BottomNavigationBar containing AddPatientInfo and AddPatientImages pages. All of these three are Stateful widgets.
By default
So I wrapped the tab pages in Stack widget and now it keeps the state of the form intact. I am not sure if this is the right way to go but it does the job.
Here is the code:
AddPatientView (parent)
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;
});
},
),
);
}
}
From the documentation on 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).
So in your example, before you return the Scaffold just call super.build:
Widget build(BuildContext context) {
super.build(context);
return Scaffold(...);
}
If you want AutomaticKeepAliveClientMixin to continue working, please use PageView to wrap the body, the code should like this
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);
},
),
);
}
}
but if you just want to keep page state, I suggest you use IndexedStack, it's very simple,no need AutomaticKeepAliveClientMixin, the code should like this
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;
});
},
),
);
}
}