Skip to content

Instantly share code, notes, and snippets.

@tolo
Last active November 13, 2025 00:02
Show Gist options
  • Select an option

  • Save tolo/f7e6c30cad3ac76085d75255ba509f10 to your computer and use it in GitHub Desktop.

Select an option

Save tolo/f7e6c30cad3ac76085d75255ba509f10 to your computer and use it in GitHub Desktop.
Example showing how to use go_router to build persistent nested navigation (i.e. separate nested navigation trees) with a BottomNavigationBar.
// This temporary implementation is now obsolete, see instead:
// https://pub.dev/documentation/go_router/latest/go_router/StatefulShellRoute-class.html
@esDotDev

esDotDev commented Oct 21, 2022

Copy link
Copy Markdown

Weird... so that must mean that despite the root Navigator being offstage, it's internal Overlay is still accessible? INTERESTING!

@tolo

tolo commented Oct 21, 2022

Copy link
Copy Markdown
Author

No, the root navigator is never offstage, only the sibling navigators in the IndexStack used for the bottom navigation. That is, at any point in time, there will only be one nested navigator β€œonstage”, and the parent (root) navigator will remain onstage at all times.

@esDotDev

Copy link
Copy Markdown

@tolo

tolo commented Oct 22, 2022

Copy link
Copy Markdown
Author

Ok, this line threw me off: https://gist.github.com/tolo/f7e6c30cad3ac76085d75255ba509f10#file-nested_navigation_shell_route-dart-L126

Right, yeah, that's the ugly bit with this workaround, which you won't get with flutter/packages#2650. But that Navigator is anyway the one created by ShellRoute, not the root one. So it's just hiding an obsolete Navigator.

@amerblackbird

Copy link
Copy Markdown

Offstage widget cause main screen build twice.

@hmbenhaim

hmbenhaim commented Nov 22, 2022

Copy link
Copy Markdown

Offstage widget cause main screen build twice.

It's amazing just i have 1 issue.
just burn a few hours till I found it. when the keyboard gets visible offstage gets called and then rebuild the all page, again and again, so it's impossible to use it with text field on android, on desktop it fine but still rebuilds many times

@davidhicks980

Copy link
Copy Markdown

Excellent fix @tolo !

One small addition. If you are having trouble with hero animations, I'm fairly certain you can add a HeroController() observer to your nested Navigator. From what I can tell from the docs, MaterialApp usually adds this automatically.

 final heroController = HeroController();

  Widget buildNavigator(BuildContext context) {
    if (pages.isNotEmpty) {
      return Navigator(
        observers: [heroController],
        key: navigatorKey,
        pages: pages,
        onPopPage: _handlePopPage,
      );
    } else {
      return const SizedBox.shrink();
    }
  }

@tolo

tolo commented Dec 4, 2022

Copy link
Copy Markdown
Author

@davidhicks980, actually support for navigation observers (and hero controllers) is being implemented in the PR flutter/packages#2664. Hoping that will be finished soon so flutter/packages#2650 can benefit from it.

My main focus right not is to complete flutter/packages#2650 so it can be merged into go_router. @amerblackbird and @hmbenhaim, please have a look at that branch and the corresponding sample (stateful_shell_route.dart) there, and see if that works better. If not, please add a comment in flutter/packages#2650.

@hmbenhaim

hmbenhaim commented Dec 4, 2022

Copy link
Copy Markdown

@amerblackbird and @hmbenhaim, please have a look at that branch and the corresponding sample (stateful_shell_route.dart) there, and see if that works better. If not, please add a comment in flutter/packages#2650.

Hi @tolo I have tried this branch and this sample it works amazing so simple and so good and perform very well. I hadn't any issues with it so far I cloned this branch and I'm using it directly once it merge I'll use the library again. Waiting for the merge. Thank you!

@tolo

tolo commented Dec 5, 2022

Copy link
Copy Markdown
Author

Happy to hear @hmbenhaim! 😊

@taringi

taringi commented Jan 29, 2023

Copy link
Copy Markdown

Mate, you are a legend! Thanks a lot! 🍻

@tolo

tolo commented Jan 29, 2023

Copy link
Copy Markdown
Author

Mate, you are a legend! Thanks a lot! 🍻

πŸ™πŸ˜ŠπŸ»

@hazzo

hazzo commented Feb 26, 2023

Copy link
Copy Markdown

Here are my 2 cents until the PR adding support for this use case it's merged. If you updated to go_router 6.0.7+ this was introduced:

Use HeroControllerScope for nested Navigator that fixes Hero Widgets not animating in Nested Navigator.

So the above gist won't work until a small change it's made to work with 6.0.7 versions and above.
On the ScaffoldWithNavBar widget inside the BottomTabBarShellRoute the currentNavigator prop can't be casted to Navigator directly because the builder method will not return now a Navigatorbut instead a HeroControllerScope.

So in line 128 this change should be done to make the gist work:

ScaffoldWithNavBar(tabs: tabs, key: scaffoldKey,
  currentNavigator: (fauxNav as HeroControllerScope).child as Navigator,
  currentRouterState: state, routes: routes),
]);

@tanhsnkt1997

Copy link
Copy Markdown

why in StatefulWidget i call @OverRide
void initState() {
super.initState();
print("-----RUN------ ")}

  • At tab:: firstly -----RUN------ call double, but since the 2nd time onwards it only calls 1 time. Please help me :(

@Zeehshan

Copy link
Copy Markdown

Here are my 2 cents until the PR adding support for this use case it's merged. If you updated to go_router 6.0.7+ this was introduced:

Use HeroControllerScope for nested Navigator that fixes Hero Widgets not animating in Nested Navigator.

So the above gist won't work until a small change it's made to work with 6.0.7 versions and above. On the ScaffoldWithNavBar widget inside the BottomTabBarShellRoute the currentNavigator prop can't be casted to Navigator directly because the builder method will not return now a Navigatorbut instead a HeroControllerScope.

So in line 128 this change should be done to make the gist work:

ScaffoldWithNavBar(tabs: tabs, key: scaffoldKey,
  currentNavigator: (fauxNav as HeroControllerScope).child as Navigator,
  currentRouterState: state, routes: routes),
]);

type '_CustomNavigator' is not a subtype of type 'HeroControllerScope' in type cast

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment