Tab routing with auto_route

·

3 min read

In this post, we will explore the functionality of tab routing in auto_route. It offers the AutoTabsRouter, which allows seamless transitions between various tabs while maintaining the state of offstage routes.

Basic setup

  1. Create a Wrapper Page for the Tab This wrapper page serves as the starting point for the navigation stack within the tab. It acts as a router for the specific tab. It's responsible for managing the navigation stack and handling the transition between different screens within the tab.

  2. Create the Actual View Widget for the Tab This is the content or the main screen that users see when they select a specific tab. It's the widget that represents the tab itself.

  3. Place Any Pages in the Tab as Children of the Wrapper Page Inside the wrapper page, you define the routes and screens that belong to the tab. These screens are added as children to the wrapper page, allowing users to navigate between them within that tab.

Let's see what it looks like in code.

router_tabs.dart

@RoutePage(name: 'SettingTab')
class SettingTabPage extends AutoRouter {
  const SettingTabPage({super.key});
}

@RoutePage(name: 'UserTab')
class UserTabPage extends AutoRouter {
  const UserTabPage({super.key});
}

user_tab_view_page.dart

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';

@RoutePage()
class UserTabViewPage extends StatelessWidget {
  const UserTabViewPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column();
  }
}

setting_tab_view_page.dart

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';

@RoutePage()
class SettingTabViewPage extends StatelessWidget {
  const SettingTabViewPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column();
  }
}

app_router.dart

@AutoRouterConfig()
class AppRouter extends $AppRouter {
  @override
  List<AutoRoute> get routes => [
        AutoRoute(
          initial: true,
          page: HomeRoute.page,
          children: [
            AutoRoute(
              page: UserTab.page,
              children: [
                AutoRoute(
                  page: UserTabViewRoute.page,
                  initial: true,
                ),
              ],
            ),
            AutoRoute(
              page: SettingTab.page,
              children: [
                AutoRoute(
                  page: SettingTabViewRoute.page,
                  initial: true,
                ),
              ],
            ),
          ],
        ),
      ];
}

home_page.dart

@RoutePage()
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AutoTabsRouter.tabBar(
      routes: [
        UserTab(),
        SettingTab(),
      ],
      builder: (context, child, tabsRouter) {
        final tabsRouter = AutoTabsRouter.of(context);

        return Scaffold(
          body: child,
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: tabsRouter.activeIndex,
            onTap: tabsRouter.setActiveIndex,
            items: [
              BottomNavigationBarItem(
                label: 'User',
                icon: Icon(Icons.person_2_outlined),
              ),
              BottomNavigationBarItem(
                label: 'Setting',
                icon: Icon(Icons.settings_outlined),
              ),
            ],
          ),
        );
      },
    );
  }
}

Navigation between tabs

We can use context.pushRoute() and context.navigateTo() to navigate between tabs.

context.pushRoute(): Use this method to push another page into the current tab's navigation stack. It allows you to navigate to a new screen while staying within the current tab.

context.navigateTo(): Use this method to navigate to a different tab or switch tabs. It's useful for scenarios where you want to move from one tab to another.

Let's see some actual code and how it can be used.

@RoutePage()
class SettingTabViewPage extends StatelessWidget {
  const SettingTabViewPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ListTile(
          title: Text('Open Theme Setting Page'),
          onTap: () {
            context.pushRoute(ThemeSettingRoute());
          },
        ),
        ListTile(
          leading: Icon(Icons.person_2_outlined),
          title: Text('Navigate to User Tab'),
          onTap: () {
            context.navigateTo(UserTab());
          },
        )
      ],
    );
  }
}

ThemeSettingRoute is defined at the same level as SettingTabViewPage, so we can use context.pushRoute(ThemeSettingRoute()); to push it to the current tab's stack.

app_router.dart

            AutoRoute(
              page: SettingTab.page,
              children: [
                AutoRoute(
                  page: SettingTabViewRoute.page,
                  initial: true,
                ),
                AutoRoute(
                  page: ThemeSettingRoute.page,
                ),
              ],
            ),

we use context.navigateTo(UserTab()); to navigate to UserTab, and if we want we can also do something like context.navigateTo(UserTab(children:[EditProfileRoute()]));, which will directly take us to the EditProfileRoute in UserTab.