Featured Image
Software Development

Build Complex Navigation Stack with Flutter

Have you ever come across a situation where you needed to show the pre-created stack of screens on the app when the user taps on notifications or the user taps on deep links. Ever wondered how that can be done in Flutter?

Check out this behavior,

Showed stack of screens when the app is launched

Here, if you see when the app is launched there are already two screens on top of the root screen.

So, how it’s possible in Flutter?

If we observe the behavior closely, we know that it’s all about navigation. When it comes to navigation every Flutter developer has heard about the Navigator widget. It manages the screen navigation in Flutter.

We normally call Navigator’s push()/pushNamed() methods to show the new screen and pop() to remove.

What we usually ignore is the Navigator itself is a StatefulWidget in Flutter. That means you can wrap it with any widget you want and create your stack of screens. 

But what if you want to show a stack of screens when the app is launched?

Well, I’ve checked the Navigator widget’s source code and found one widget parameter which will allow us to achieve this behavior.

onGenerateInitialRoutes

If you check out comments above its declaration it says,

The callback must return a list of [Route] objects with which the history will be primed.

Meaning, we can generate our own initial list of Routes (e.g. screens) and show it pre-ready when the user opens the screen with the Navigator widget at the root of the screen.

Navigator widget at the root of the screen

If you check the MaterialApp widget source code you will see that it uses WidgetApp and somewhere in the source code of WidgetApp has Navigator widget as its root widget.

Source code of WidgetApp in Android Studio
Source code of WidgetApp in Android Studio

It’s time for code!

If you see the WidgetApp’s source code, you will see it passes onGenerateInitialRoutes to the Navigator widget. Now, this parameter can be initialized in MaterialApp.

So what I’ve done is to use this parameter to pass initial widgets when the app is launched and voila! You will see those screens already stacked up.

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Navigators',
      onGenerateInitialRoutes: defaultGenerateInitialRoutes,
      debugShowCheckedModeBanner: false,
      onGenerateRoute: generateRoute,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
    );
  }
}

Here is the defaultGenerateInitialRoutes() method,

List defaultGenerateInitialRoutes(String initialRouteName) {
  List routes = new List();
  routes.add(MaterialPageRoute(builder: (context) => RootWidget()));
  routes.add(MaterialPageRoute(builder: (context) => SecondWidget()));
  routes.add(MaterialPageRoute(builder: (context) => ThirdWidget()));
  return routes;
}

In this method, I’ve created a list of the MaterialPageRoute widget and returned it. I’ve created three widgets: RootWidgetSecondWidget, and ThirdWidget.

Navigator widget will be initialized with these routes only and show these screens when renders

GitHub repo: harshsoni1110/custom_navigation

You can use this approach to solve a couple of problems such as,

  • Show a stack of screens when the user taps the notifications or deep links and opens the application
  • Progressive feature implementation such as asking the user’s info, his photo, parents’ details, etc. step by step.
  • One can also provide continuation for these progressive features using BLoc (e.g. When the user has left the flow in between and comes back later to continue)

Hope you find this information about Navigator insightful. Cheers!

References

Thanks for reading this article. Leave a comment below if you have any doubts or feedback about this article. You can clap if you find this article helpful.

author
Harsh Soni
Harsh is a developer with about a decade (if not more) of expertise in building mobile apps. More of a doer, less of a talker, he likes to keep his mind occupied, and has an eye for understanding systems in their barebones, helping him be his creative best, impacting users' lives for the better. Enjoys building reusable & scalable systems, reading a book in a quiet beautiful place, or learning something new.