Reputation: 890
I have two main widgets inside of stack, which placed inside of main route(screen):
Each page of pageView is wrapped inside of CustomNavigator widget, and list of keys for navigators are placed inside of main route(screen). Navigation by using bottom navigation bar works fine, but when pushing to another rote inside of page and going to another page and back, the state of page with pushed route become to default state, what can I do with it? Here is my main screen's state:
const String MainRoute = '/';
const String AccountRoute = '/account';
const String CategoriesRoute = '/categories';
const String HomeRoute = '/home';
const String WishListRoute = '/wish_list';
const String ProductRoute = '/product';
class _MainState extends State<Main> {
int _pressedPosition = 0;
final List _screenStates = [
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
GlobalKey<NavigatorState>(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
PageView(
physics:new NeverScrollableScrollPhysics(),
controller: _pageController,
children: _mainScreens(),
),
Align(
alignment: Alignment.bottomCenter,
child: CurvedNavigationBar(
animationDuration: Duration(milliseconds: 200),
backgroundColor: Colors.transparent,
onTap: (int position) {
_bottomTapped(position);
},
height: 60.0,
items: <Widget>[...],
),
)
],
),
);
}
PageController _pageController = PageController(
initialPage: 0,
keepPage: true,
);
void _bottomTapped(int index) {
setState(() {
_pressedPosition = index;
_pageController.animateToPage(index,
duration: Duration(milliseconds: 300), curve: Curves.ease);
});
}
List<Widget> _mainScreens() {
return <Widget>[
CustomNavigator(initialRoute: HomeView(), navigatorKey: _screenStates[0],),
CustomNavigator(initialRoute: CategoriesView(), navigatorKey: _screenStates[1],),
CustomNavigator(initialRoute: ShoppingCartView(), navigatorKey: _screenStates[2],),
CustomNavigator(initialRoute: WishListView(), navigatorKey: _screenStates[3],),
CustomNavigator(initialRoute: AccountView(), navigatorKey: _screenStates[4],),
];
}
Here is Custom navigator class:
class CustomNavigator extends StatelessWidget {
final Widget initialRoute;
final GlobalKey<NavigatorState> navigatorKey;
CustomNavigator({@required this.initialRoute, @required this.navigatorKey});
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
onGenerateRoute: _routes(initialRoute),
);
}
//routing
RouteFactory _routes(Widget initialRoute) {
return (settings) {
final Map<String, dynamic> arguments = settings.arguments;
Widget screen;
switch (settings.name) {
case MainRoute:
screen = initialRoute;
break;
case ProductRoute:
screen = ProductView();
break;
default:
return null;
}
return MaterialPageRoute(builder: (BuildContext context) => screen);
};
}
}
I already read https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386, https://medium.com/@Mr_Pepe/nested-navigation-with-a-bottom-navigation-bar-using-flutter-d3c5086fbcdc and http://bizz84.github.io/2018/07/07/Multiple-Navigators-BottomNavigationBar.html but anyway these topics are too difficult to understand.
In addition found this solution, but it doesn't work: https://github.com/indatawetrust/nested-navigation-demo-flutter
HELP! Thanks))
Upvotes: 0
Views: 3294
Reputation: 623
PageView unloads tabs that aren't visible to save memory, that's why your state is getting lost. But you can force them to stay around by using the KeepAlive
machinery. See AutomaticKeepAliveClientMixin
for the simplest way to do that. That should work with the PageView used with tabs.You can use IndexedStack
instead of PageView
because it doesn't unload the widgets, it just displays the current active widget on top of others. Each Widget in IndexedStack returns its own Navigator like you are doing currently.So you can do something like this
IndexedStack(
index: _pressedPosition,
children: _mainScreens(), //return Views Here
),
)
and then on click
setState(() {
_pressedPosition = index;
});
You can use BottomNavigationBar
which is a part of Scaffold widget and made for just this purpose. Check this link for reference (the navigation part).
Upvotes: 2