I've been searching around for a good navigation/router example for Flutter but I have not managed to find one.
What I want to achieve is very simple:
The official Flutter demo for BottomNavigationBar achieves 1 but back button and routing dont't work. Same problem with PageView and TabView. There are many other tutorials that achieve 2 and 3 by implementing MaterialApp routes but none of them seem to have a persistent navigation bar.
Are there any examples of a navigation system that would satisfy all these requirements?
The solution is to define a named route, and use the named route for navigation. To work with named routes, use the Navigator.
A bottom navigation bar is a material widget that is present at the bottom of an app for selecting or navigating to different pages of the app. It is usually used in conjunction with a Scaffold, where it is provided as the Scaffold. bottomNavigationBar argument.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With