The app I am developing attempts to adopt, as much as possible, the most native experience for Android & iOS users.
To do so, the app runs a CupertinoApp and a MaterialApp.
On iOS, I use the CupertinoScaffold showing a CupertinoTabBar with BottomNavigationBarItems. It performs very well as expected:
- pages are created only once, the first time I click on a tab;
- pages are restored when returning to a previously displayed tab: in one of my tab, there is a list and its scroll position is always maintained, persisted.
on Android, the story is different: I am using the Drawer widget.
When I click on an entry, I call Navigator#push to show the associated page. However, this will keep adding new instances of each entry's page in the stack.
I don't seem to be able to return to an existing page. At least, not how I can do it with iOS.
Looking at the Navigator I see functions that seem to achieve what I am looking for:
popUntil=> will show my existing screen, but at the expanses of all the other ones that will therefore make a sacrifice for the sake of just one page. So much ado for nothing...pushReplacement=> will show a new instance of the target page and destroy the current one. Not desirable.
What am I missing ? How can I achieve that the CupertinoTabBar seems to be able to do?
Well, I solved my issue by taking another direction.
Simply put I don't think there is a way, with the
Navigatorto achieve what I want.The solution I find out was: Keep state of widgets with Bottom Navigation Bar in Flutter
This guide suggests to use a
IndexedStackthat displays only one child at the time while keeping its state.So this is how I managed to make it work:
MaterialApphometo be a custom stateful widget calledMaterialHomePageMaterialHomePagebuilds aScaffold:AppBarand its title (the title of the active page);drawerand its arguments (more on that later)bodyis that so-called wonderfulIndexedStack:childrento be the list of pages / widgets, the same pages available in the drawerindexto be the property_selectedPageIndexof yourMaterialHomePagesetStateoccurs inside of which you may update the_selectedPageIndexproperty as well as_selectedPageIndexproperty`.Drawer:Functionwith the target page title & indexListTile) as pages you have declared in theIndexedStackdisplayed inMaterialHomePage.At the end, what happens:
MaterialHomePagegets notified (via callback) of the user choice which triggers asetStagethat will both:IndexedStackwithindex = 3AppBar's titleand voilà there you go: each page gets retained, no loss of state and a smooth navigation.
NB: if the user uses the Android's back button feature, at this point it will close the app since the
Navigatorstack is empty. Maybe there is a way to listen for such an event if you desire to default to the first entry / page (displayed at launch) if the user was in a another page.NB2: I also wonder if there is a way to animate page transitions.
PS: Let me know if the answers is a fine solution in which case I'll validate it. Or if you find a proper way to achieve it.