_Checkout our extensive docs to learn more about this package, the inspiration behind it and how to use it._
NavbarRouter is a complete package to handle all your BottomNavigationBar needs. It provides a simplest api to achieve the advanced features of BottomNavigationBar making the user experience of your app much better. You only need to specify the NavbarItems and the routes for each NavbarItem and NavbarRouter will take care of the rest.
Most of the features which this package provides are mainly to improve the user experience by handling the smallest things possible.
See the demo app here
You can choose between different NavbarTypes using the NavbarDecoration.navbarType
property. This allows you to choose between the default NavbarType.standard
and NavbarType.notched
NavbarTypes.
NavbarType.standard (default) | NavbarType.notched |
---|---|
NavbarType.material3 | NavbarType.floating |
---|---|
Heres a sample app built using this package to see how it works.
video demo of the sample app
This package will help you save atleast 50% lines of code in half the time required to implement the above features. Heres the same sample app without the package which requires around 800 lines of code.
Run from the root of your flutter project.
flutter pub add navbar_router
Example
class HomePage extends StatelessWidget {
HomePage({Key? key}) : super(key: key);
List<NavbarItem> items = [
NavbarItem(Icons.home_outlined, 'Home',
backgroundColor: mediumPurple,
selectedIcon: Icon(
Icons.home,
size: 26,
)),
NavbarItem(Icons.shopping_bag_outlined, 'Products',
backgroundColor: Colors.orange,
selectedIcon: Icon(
Icons.shopping_bag,
size: 26,
)),
NavbarItem(Icons.person_outline, 'Me',
backgroundColor: Colors.teal,
selectedIcon: Icon(
Icons.person,
size: 26,
)),
];
final Map<int, Map<String, Widget>> _routes = const {
0: {
'/': HomeFeeds(),
FeedDetail.route: FeedDetail(),
},
1: {
'/': ProductList(),
ProductDetail.route: ProductDetail(),
},
2: {
'/': UserProfile(),
ProfileEdit.route: ProfileEdit(),
},
};
@override
Widget build(BuildContext context) {
return NavbarRouter(
errorBuilder: (context) {
return const Center(child: Text('Error 404'));
},
onBackButtonPressed: (isExiting) {
return isExiting;
},
destinationAnimationCurve: Curves.fastOutSlowIn,
destinationAnimationDuration: 600,
decoration:
NavbarDecoration(navbarType: BottomNavigationBarType.shifting),
destinations: [
for (int i = 0; i < items.length; i++)
DestinationRouter(
navbarItem: items[i],
destinations: [
for (int j = 0; j < _routes[i]!.keys.length; j++)
Destination(
route: _routes[i]!.keys.elementAt(j),
widget: _routes[i]!.values.elementAt(j),
),
],
initialRoute: _routes[i]!.keys.first,
),
],
);
}
}
When the selected NavbarItem is at the root of the navigation stack, pressing the Back button (On Android) will by default trigger app exit.
For instance:
Your app has three tabs and you navigate from Tab1 -> Tab2 -> Tab3
BackButtonBehavior.exit
(default)
when you press Back Button (on Tab3) your app will exit
BackButtonBehavior.rememberHistory
,
This will switch the navbar current index to the last selected NavbarItem (Tab 2) from the navbarHistory.
You can read more about this feature here.
You can have smooth Transitions between NavbarDestinations by setting the destinationAnimationCurve
and destinationAnimationDuration
properties.
defaults to
destinationAnimationCurve: Curves.fastOutSlowIn,
destinationAnimationDuration: 300,
You can hide or show bottom navigationBar with a single line of code from anywhere in the widget tree. This allows you to handle useCases like scroll down to hide the navbar or hide the navbar on opening the drawer.
NavbarNotifier.hideBottomNavBar = true;
Hide/show navbar on scroll | Hide/show navbar on drawer open/close | Consistent behavior across all Navbars |
---|---|---|
You can show a snackbar on top of the navbar by using the NavbarNotifier.showSnackBar
method.
Note: You will need to wrap your NavbarRouter within a builder for this to work see the example for more details.
NavbarNotifier.showSnackBar(
context,
"This is shown on top of the Floating Action Button",
/// offset from bottom of the screen
bottom: state.hasFloatingActionButton ? 0 : kNavbarHeight,
);
And hide it using the NavbarNotifier.hideSnackBar
method.
NavbarNotifier.hideSnackBar(context);
_navbarrouter provides a onBackButtonPressed
callback to intercept events from android back button, giving you the ability to handle app exits so as to prevent abrupt app exits without users consent. (or you might want to implement double press back button to exit).
This callback method must return true
to exit the app and false other wise.
sample code implementing double press back button to exit
onBackButtonPressed: (isExitingApp) {
if (isExitingApp) {
newTime = DateTime.now();
int difference = newTime.difference(oldTime).inMilliseconds;
oldTime = newTime;
if (difference < 1000) {
hideSnackBar();
return isExitingApp;
} else {
showSnackBar();
return false;
}
} else {
return isExitingApp;
}
},
NavbarItem(Icons.home_outlined, 'Home',
backgroundColor: colors[0],
selectedIcon: const Icon(
Icons.home,
size: 26,
),
badge: const NavbarBadge(
badgeText: "11",
showBadge: true,
)),
NavbarNotifier.makeBadgeVisible
and update using NavbarNotifier.updateBadge
method from any part of the tree. NavbarRouter(
errorBuilder: (context) {
return const Center(child: Text('Error 404'));
},
isDesktop: size.width > 600 ? true : false,
decoration: NavbarDecoration(
isExtended: size.width > 800 ? true : false,
navbarType: BottomNavigationBarType.shifting),
...
...
);
For detailed description of all the features and properties please visit the documentation
Read more in a medium blog post for detailed explanation.
Youtube: Heres a discussion I had with Allen Wyma from Flying high with Fluter regarding this package.
Contributions are welcome! for more details on how to contribute, please see the contributing guide