Navigator Widget: A walkthrough to custom navigation

Umesh Basnet
3 min readSep 30, 2022

--

If you have used Instagram, then you might have noticed that each bottom navigation tab has its own navigation stack and history. When you move to open a new child screen in one tab then it won’t replace other tabs. If you are looking for similar things then you have come to the right blog. I am going to show you how you can implement such functionality yourself.

If you have heard about the Navigator widget then kudos to you. If you have not heard then that's why I am here. You might have used Navigator.push and Navigator.pop already in the app. This is the root navigation that is available for the MaterialApp. When we use a Navigator widget then it is the nested navigator within our root navigation.

Let’s start with coding.

I will create a page view with the bottom navigation. I will publish the code here but will not go into detail about them as that’s not the scope of this article. If you want to know about them then you can write in the comment and I will make a separate blog about it.

Most of the code is simple. But if you look at line number 23, I have returned a Navigator widget with a custom onGenerateRoute and dashboard as initialRoute for the dashboard tab. In line 28, it is a normal custom widget ProfileTab.

This is a normal route generation in which I have defined different screens I can use throughout my app.

This is it, all of our setups have been completed. All we need to do is navigate to a different screen and see the result. Let’s navigate to the FirstScreen from Dashboard.

Here, I have simply navigated to the first screen as you would normally, and here is the result.

As you can see, there are two tabs dashboard and profile. Normally when you push a new screen, it would cover up the whole screen. But here, when we push FirstScreen from the dashboard, the bottom navigation is still visible and the FirstScreen is only above DashboardTab. Also, you can easily navigate to the profile tab and when you go to the dashboard screen, the first screen is still in the navigation stack of the dashboard navigator. When you press back in the FirstScreen we can go back to the dashboard tab.

What if we want to push a new screen in the root navigator? Well, it can easily be done by getting the instance of the navigator with Navigator.of(context, rootNavigator: true). Then you can do push or pop as per the requirement.

Let’s see an example of that. Below is the code inside the FirstScreen.

If you look at line 29, we are using the root navigator to push the new screen while pressing the second button. This will show a new screen on top of our existing screen. But when we are pressing the first button, we are showing are not using the root navigator. This will get us the first Navigator widget it can find in the widget tree above our context, which is the Navigator widget we are using in the Dashboard tab. That’s why it pushes the new screen on top of the Dashboard tab.

Here is the result we get:

In this way, we can easily implement any kind of nested navigation. This is not useful just in bottom navigation but also in drawers, or login/sign-up flow as well.

You can also use an already existing package like this persistent_bottom_nav_bar for a highly customizable bottom nav if this fulfills your requirements.

If you want the whole source code: https://github.com/umuieme/flutter_custom_navigation

--

--