Search packages, repositories and app categories

Package detailsv1.0.9

nested_navigators

Flutter widget for implementing multiple nested navigators with their own route stacks.

30-day downloads
22
Likes
17
Pub points
40

Install package

flutter pub add nested_navigators

Package Overview

Package selection guidance compiled from public package information, community data, and project usage.

NestedNavigators is a Flutter package that enables the implementation of multiple nested navigators, each managing its own independent route stack. It simplifies complex navigation scenarios in apps with layered UIs, such as tabbed interfaces or modals within screens. By allowing isolated navigation behavior per navigator, it prevents unintended route interference and improves maintainability. The package integrates seamlessly into existing Flutter projects and supports dynamic routing within nested structures.

Use cases

  • Complex tabbed interfaces
  • Modal dialogs within screens
  • Multi-level navigation flows
  • Independent route stacks in components
  • Nested screen transitions

Key features

  • Per-navigator route stack isolation
  • Support for deep linking
  • Clean separation of navigation logic
  • Easy integration with MaterialApp
  • Dynamic route management

Suitable for

  • Apps with multiple navigation layers
  • Developers managing complex routing
  • UIs requiring independent navigation contexts
  • Projects using modular screen architecture
  • Teams prioritizing maintainable navigation code

Considerations

  • Requires careful state management
  • May increase app complexity if overused
  • Not needed for simple navigation
  • Limited documentation compared to core Flutter
  • Potential performance overhead with excessive nesting

Original README

Original README snapshot from the linked source repository. Visit the repository for the latest content.

NestedNavigators

Flutter widget for implementing multiple nested navigators with their own route stacks.

Usage

To use, you must at least specify two arguments items and generateRoute:

class RootPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _RootPageState();
}

class _RootPageState extends State<RootPage> {
  @override
  Widget build(BuildContext context) {
    return NestedNavigators(
      items: {
        NestedNavItemKey.blue: NestedNavigatorItem(
          initialRoute: Routes.blue,
          icon: Icons.access_time,
          text: "Blue",
        ),
        NestedNavItemKey.red: NestedNavigatorItem(
          initialRoute: Routes.red,
          icon: Icons.send,
          text: "Red",
        ),
        NestedNavItemKey.green: NestedNavigatorItem(
          initialRoute: Routes.green,
          icon: Icons.perm_identity,
          text: "Green",
        ),
      },
      generateRoute: Routes.generateRoute,
    );
  }
}

See Routes.generateRoute()

By default NestedNavigators displays BottomNavigationBar, but you can hide it if you want:

clearStackAfterTapOnCurrentTab: false

You can customize BottomNavigatosBar items in two ways:

  • configure BottomNavigationBarItem:
buildBottomNavigationItem: (key, item, selected) => BottomNavigationBarItem(
           icon: Icon(
             item.icon,
             color: Colors.blue,
           ),
           title: Text(
             item.text,
             style: TextStyle(fontSize: 20),
           ),
         )
  • Define your own widget:
buildCustomBottomNavigationItem: (key, item, selected) => Container(
            height: 60,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                Icon(
                  item.icon,
                  size: 24,
                  color: selected ? Colors.blue : null,
                ),
                Text(
                  item.text,
                  style: TextStyle(fontSize: 20, color: selected ? Colors.blue : null),
                ),
              ],
            ),
          )

Initial selected navigator:

  • If number of navigators is even number, than it will be the first elemnt of items;
  • If number of navigators is odd number, than it will be the middle element of items;
  • You can specify your navigator key:
 initialNavigatorKey: NestedNavItemKey.green

You can specify the color of ripple effect in your app theme or in bottomNavigationBarTheme:

bottomNavigationBarTheme: Theme.of(context).copyWith(
       splashColor: Colors.blue[100],
   )

By default, if a user clicks on an already selected tab item, the route stack will be cleared and the initial route will be displayed. You can disable this option:

clearStackAfterTapOnCurrentTab: false

When you navigate to another route within nested navigator, you can hide BottomNavigatorsBar for specific route, just add hideNavTabBar: true to route arguments:

Navigator.of(context).pushNamed(
                    Routes.red,
                    arguments: {
                      hideNavTabBar: true,
                    },
                  );

You can select another navigator from your routes:

NestedNavigatorsBlocProvider.of(context).select(NestedNavItemKey.green)

You can also switch displayed navigator and at the same time make navigation in the new navigator:

NestedNavigatorsBlocProvider.of(context).selectAndNavigate(
                      NestedNavItemKey.green,
                      (navigator) => navigator.pushNamed(
                            Routes.green,
                            arguments: {
                              ArgumentKeys.value: 100,
                            },
                          ));

Add NestedNavigatorsBlocProvider to app widget if you want to use the root navigator and need access to nested navigators from there:

class App extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _AppState();
}

class _AppState extends State<App> {
  final NestedNavigatorsBloc _bloc = NestedNavigatorsBloc<NestedNavItemKey>();

  @override
  Widget build(BuildContext context) {
    return NestedNavigatorsBlocProvider(
      bloc: _bloc,
      child: MaterialApp(
        title: 'Flutter Demo',
        home: RootPage(),
        onGenerateRoute: (routeSettings) => Routes.generateRoute(routeSettings),
      ),
    );
  }
}

You can use Drawer instead of BottomNavigationBar, use drawer or endDrawer for this:

drawer: (items, selectedItemKey, selectNavigator) => Drawer(
            child: ListView(
              children: items.entries
                  .map((entry) => ListTile(
                        title: Text(
                          entry.value.text,
                          style: TextStyle(
                            color: entry.key == selectedItemKey
                                ? Colors.blue
                                : null,
                          ),
                        ),
                        trailing: Icon(
                          entry.value.icon,
                          color:
                              entry.key == selectedItemKey ? Colors.blue : null,
                        ),
                        onTap: () => selectNavigator(entry.key),
                      ))
                  .toList(),
            ),
          ),

Also you can open drawers from your pages:

NestedNavigatorsBlocProvider.of(context).actionWithScaffold(
                  (scaffoldState) => scaffoldState.openDrawer(),
                );

Categories

Source repository

Projects using this package

No data available yet.