Flutter persistent navigation bar with named routes?
All of your 3 requirements can be achieved by using a custom Navigator.
The Flutter team did a video on this, and the article they followed is here: https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386
Basically, you will need to wrap the body of your Scaffold in a custom Navigator
:
class _MainScreenState extends State<MainScreen> {
final _navigatorKey = GlobalKey<NavigatorState>();
// ...
@override
Widget build(BuildContext context) {
return Scaffold(
body: Navigator(
key: _navigatorKey,
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
// Manage your route names here
switch (settings.name) {
case '/':
builder = (BuildContext context) => HomePage();
break;
case '/page1':
builder = (BuildContext context) => Page1();
break;
case '/page2':
builder = (BuildContext context) => Page2();
break;
default:
throw Exception('Invalid route: ${settings.name}');
}
// You can also return a PageRouteBuilder and
// define custom transitions between pages
return MaterialPageRoute(
builder: builder,
settings: settings,
);
},
),
bottomNavigationBar: _yourBottomNavigationBar,
);
}
}
Within your bottom navigation bar, to navigate to a new screen in the new custom Navigator
, you just have to call this:
_navigatorKey.currentState.pushNamed('/yourRouteName');
To achieve the 3rd requirement, which is Navigator.pop
taking you to the previous view, you will need to wrap the custom Navigator
with a WillPopScope
:
@override
Widget build(BuildContext context) {
return Scaffold(
body: WillPopScope(
onWillPop: () async {
if (_navigatorKey.currentState.canPop()) {
_navigatorKey.currentState.pop();
return false;
}
return true;
},
child: Navigator(
// ...
),
),
bottomNavigationBar: _yourBottomNavigationBar,
);
}
And that should be it! No need to manually handle pop or manage a custom history list.
CupertinoTabBar behave exactly same as you described, but in iOS style. It can be used in MaterialApps
however.
Sample Code