I'm trying to preserve the state of widget pages when switching between widgets using BottomNavigationBar
. I've read here that I can do this using IndexedStack
, however, that doesn't work in my case for two reasons:
- The
Scaffold
in which the pages are displayed gets rebuilt when switching between pages because for some, but not all, pages theScaffold
should be extended:Scaffold( extendBody: _pageIndex == 1, ...)
- The pages should be built for the first time just when the page is opened for the first time and not right from the start
Here's a small example that shows that IndexStack
is not working as intended because the Scaffold
rebuilds:
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int _pageIndex = 1;
List<Widget> _pages = [Text("hi"), Counter()];
@override
Widget build(BuildContext context) {
return Scaffold(
extendBody: _pageIndex == 1,
appBar: AppBar(),
body: IndexedStack(
children: _pages,
index: _pageIndex,
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Goto 0',),
BottomNavigationBarItem(icon: Icon(Icons.business), label: 'Goto 1',),
],
currentIndex: _pageIndex,
onTap: (int index) {
setState(() {
_pageIndex = index;
});
print("idx " + _pageIndex.toString());
},
),
);
}
}
Demo showing that the state is not preserved
This is the Counter which can be replaced by any other stateful widget:
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
//this part is not important, just to show that state is lost
class _CounterState extends State<Counter> {
int _count = 0;
@override
void initState() {
_count = 0;
super.initState();
}
@override
Widget build(BuildContext context) {
return Center(
child: TextButton(
child: Text("Count: " + _count.toString(), style: TextStyle(fontSize: 20),),
onPressed: () {
setState(() {
_count++;
});
},
),
);
}
}