🤔 : Hmm, I wonder how to keep BottomNavigationBar fixed while transition in Flutter?
🌐 : go_router, beamer, qlevar_router, etc...
😵 : Wait, I just want a persitent nav bar, I don't need deep linking, URL based navigation, or back buttons for brower... Is there any other easy way?
🌐 : ...
🙄: 🤯
👼 : There's navigator_scope, bro.
A simple package for nested navigation. No need to learn a bunch of new APIs. It will work exactly as you imagine.
Navigator 2.0 is powerful and go_router is friendly. However, there are still cases where these tools are overkill, and in those cases traditional navigator APIs such as pop
and push
are more suitable due to its simplicity. This is where navigator_scope comes in. It extracts the nested navigation mechanism from CupertinoTabScaffold and makes it more generalized for use in MaterialDesign widgets.
- Simple to use: You don't need to learn a bunch of new APIs.
- Works with any tab based widgets: Since it is completely independent of tabs, it can be used not only with builtin tabs such as BottomNavigationBar and NavigationDrawer, but also a variety of third party packages like animated_bottom_navigation_bar and curved_navigation_bar.
- Only supports non-named routes: For simplicity, this package doesn't support
Navigator.pushNamed
or URL based routing.
Available at pub.dev.
flutter pub add navigator_scope
There is an example app that uses this package with NavigationBar.
git clone git@github.com:fujidaiti/navigator_scope.git
cd example
flutter pub get
flutter run
Use NestedNavigator
as a local navigator, and NavigatorScope
as a hub of the navigators. NavigatorScope
keeps the state of each tab even if it disappears after the transition. If you want to change the active tab, just rebuild NavigatorScope
with new currentDestination
. That's all.
Scaffold(
bottomNavigationBar: NavigationBar( // Use your favorite nav bar
selectedIndex: selectedTabIndex,
destinations: tabs,
...
),
body: NavigatorScope( // A hub of local navigators
currentDestination: selectedTabIndex,
destinationCount: tabs.length,
destinationBuilder: (context, index) {
return NestedNavigator( // A local navigator
// Create the default page for this navigator
builder: (context) => Container(),
);
},
),
);
You can use Navigator.push
to navigate to a new page, and Navigate.pop
to go back. The other imperative navigation APIs such as Navigator.popUntil
can also be used.
Navigator.of(context).push(...);
If you want to show a dialog that covers the entire screen, use the root navigator instead of a local navigator.
showDialog(
context: context,
useRootNavigator: true,
...,
);
If you have any question, feel free to ask them on the discussions page.
If you find any bugs or have suggestions for improvement, please create an issue or a pull request on the GitHub repository. Contributions are welcome and appreciated!