Milad-Akarie / auto_route_library

Flutter route generator
MIT License
1.59k stars 405 forks source link

Nested TabBar Navigation not Working as Expected #1790

Open kuyazee opened 12 months ago

kuyazee commented 12 months ago

As you can see in this recording, it is navigating on the wrong location for some reason

Am I doing something wrong?

https://github.com/Milad-Akarie/auto_route_library/assets/17846698/b75047ba-0b94-4001-ab69-893ae77dc52e

Here's my router setup

import 'package:auto_route/auto_route.dart';

import 'app_router.gr.dart';

@AutoRouterConfig(replaceInRouteName: 'Screen,Route')
class AppRouter extends $AppRouter {
  List<AutoRoute> get childRoutes => [
        AutoRoute(
          path: 'fake',
          page: FakeRoute.page,
        ),
      ];

  @override
  RouteType get defaultRouteType => const RouteType.adaptive();

  @override
  List<AutoRoute> get routes => [
        AutoRoute(
          path: '/',
          initial: true,
          page: SplashRoute.page,
        ),
        AutoRoute(
          path: '/dashboard',
          page: TabBarRoute.page,
          children: [
            // RedirectRoute(path: '', redirectTo: 'home'),
            AutoRoute(
              path: '',
              page: HomeRoute.page,
              children: childRoutes,
            ),
            AutoRoute(
              path: 'menu',
              page: MenuRoute.page,
              children: childRoutes,
            ),
          ],
        ),
      ];
}

Application Setup


class Application extends StatefulWidget {
  const Application({super.key});

  @override
  State<Application> createState() => _ApplicationState();
}

class _ApplicationState extends State<Application> {
  final AppRouter router = AppRouter();
  late GlobalKey<NavigatorState> navigatorKey;

  @override
  void initState() {
    navigatorKey = GlobalKey<NavigatorState>();

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      key: navigatorKey,
      debugShowCheckedModeBanner: false,
      routerDelegate: AutoRouterDelegate(
        router,
        navigatorObservers: () => <NavigatorObserver>[
          AutoRouteObserver(),
        ],
      ),
      routeInformationParser: router.defaultRouteParser(includePrefixMatches: true),

      builder: (BuildContext context, Widget? child) {
        if (child != null) {
          return MediaQuery(
            data: MediaQuery.of(context).copyWith(textScaleFactor: 1),
            child: child,
          );
        }
        return const SizedBox.shrink();
      },
      // routerConfig: _appRouter.config(),
    );
  }
}

Sample Screens

@RoutePage()
class SplashScreen extends StatelessWidget {
  const SplashScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(centerTitle: true, title: Text('hello')),
      backgroundColor: Colors.white,
      body: Center(
        child: TextButton(
          child: const Text(
            'Go to Tabbar',
            style: TextStyle(color: Colors.black),
          ),
          onPressed: () => context.router.replace(TabBarRoute()),
        ),
      ),
    );
  }
}

@RoutePage()
class TabBarScreen extends StatelessWidget {
  const TabBarScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return AutoTabsScaffold(
      routes: [
        HomeRoute(),
        MenuRoute(),
      ],
      bottomNavigationBuilder: (context, tabsRouter) => BottomNavigationBar(
        currentIndex: tabsRouter.activeIndex,
        onTap: (int index) => tabsRouter.setActiveIndex(index),
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.abc), label: 'home'),
          BottomNavigationBarItem(icon: Icon(Icons.abc), label: 'menu'),
        ],
      ),
    );
  }
}

@RoutePage()
class IndexedScreen extends StatelessWidget {
  const IndexedScreen({super.key, required this.index});

  final int index;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Screen $index'),
      ),
      body: SizedBox(
        width: double.infinity,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            Text('This is Screen $index'),
            TextButton(
              child: const Text(
                'Go to new screen',
                style: TextStyle(color: Colors.black),
              ),
              onPressed: () {
                try {
                  context.router.push(FakeRoute());
                } catch (e) {
                  print(e);
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

@RoutePage()
class FakeScreen extends StatelessWidget {
  const FakeScreen({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Fake Screen'),
      ),
      body: SizedBox(
        width: double.infinity,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            TextButton(
              child: const Text(
                'Go to new screen',
                style: TextStyle(color: Colors.black),
              ),
              onPressed: () {
                try {
                  context.router.navigate(FakeRoute());
                } catch (e) {
                  print(e);
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

@RoutePage()
class HomeScreen extends StatelessWidget {
  const HomeScreen({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: SizedBox(
        width: double.infinity,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            TextButton(
              child: const Text(
                'Go to new screen',
                style: TextStyle(color: Colors.black),
              ),
              onPressed: () {
                try {
                  context.tabsRouter.navigate(MenuRoute());
                } catch (e) {
                  print(e);
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

@RoutePage()
class MenuScreen extends StatelessWidget {
  const MenuScreen({
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Menu'),
      ),
      body: SizedBox(
        width: double.infinity,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            TextButton(
              child: const Text(
                'Go to new screen',
                style: TextStyle(color: Colors.black),
              ),
              onPressed: () {
                try {
                  context.router.push(FakeRoute());
                } catch (e) {
                  print(e);
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

Flutter Doctor

[✓] Flutter (Channel stable, 3.13.2, on macOS 13.5 22G74 darwin-arm64, locale en-PH)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.2)
[✓] VS Code (version 1.84.1)
[✓] Connected device (3 available)
[✓] Network resources

Auto Route Version: 7.8.4

Pubspec

dependencies:
  flutter:
    sdk: flutter

  auto_route:

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^2.0.0
  auto_route_generator:
  build_runner:
jazz-mobility commented 11 months ago

Were you able to find a workaround? https://github.com/Milad-Akarie/auto_route_library/issues/1654#issuecomment-1806937070

jazz-mobility commented 11 months ago

Check out the example app, I was able to fix it by creating tab pages. Updated code

// This was the actual issue
@RoutePage(name: 'HomeTab')
class HomeTabPage extends AutoRouter {
  const HomeTabPage({super.key});
}

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

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

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

class AppRouter extends _$AppRouter {
  // Private constructor
  AppRouter._();

  static AppRouter shared = AppRouter._();

  @override
  List<AutoRoute> get routes => [
        AutoRoute(page: SplashRoute.page, initial: true),
        AutoRoute(page: ProductGuideRoute.page),
        AutoRoute(page: LoginRoute.page),
        AutoRoute(
          path: '/',
          page: B2BDashboardRoute.page,
          children: [
            RedirectRoute(path: '', redirectTo: 'home'),
            AutoRoute(
              path: 'home',
              page: HomeTab.page,
              children: [
                AutoRoute(path: '', page: HomeRoute.page),
              ],
            ),
            AutoRoute(
              path: 'seniors',
              page: SeniorListTab.page,
              children: [
                AutoRoute(path: '', page: LinderaSeniorListRoute.page),
                AutoRoute(path: 'seniorId:', page: MainProfileRoute.page),
              ],
            ),
            AutoRoute(
              path: 'analysis',
              page: AnalysisListTab.page,
              children: [
                AutoRoute(path: '', page: AnalysesListRoute.page),
              ],
            ),
            AutoRoute(
              path: 'more',
              page: MoreTab.page,
              children: [
                AutoRoute(path: '', page: MoreRoute.page),
              ],
            ),
          ],
        ),
      ];
}