How to Use Shell Route with GoRoute in same hierarchy Routes
How do I push from ShellRoute to GoRoute in the same hierarchy as ShellRoute using one of the NavBar buttons?
Currently, the routes of GoRouter have two values: ShellRoute and GoRoute. The Child in ShellRoute represents Home, Discover, and Shop Widget. However, NavBar has one additional fourth button in addition to the three buttons to Widget mentioned above. This button (MY) is for going to the GoRoute mentioned earlier.
As you can see from the code to be attached below, I expected this to show the Login Widget when the 4th button is pressed on ShellRoute as the GoRoute is stacked on the ShellRoute. But in reality, as ShellRoute is removed, GoRoute becomes the top stack, iOS does not have a back button, and Android shuts down the app at BackPress.
There are no examples of this in the official document examples, so I'm lost a lot. I found a similar exampleten thousand https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/shell_route.dart In the example above, GoRoute is dependent on ShellRoute. I don't want this. I want to make the Login Route accessible from anywhere.
I will attach my code and operation screen below. I need your help.
Expected results: When the fourth button is pressed, the GoRoute is stacked on the ShellRoute, and the ShellRoute reappears when the back is pressed
Actual results: When the fourth button is pressed, ShellRoute is removed, creating a GoRoute and stacking it at the top, and the app ends when you press Back.
Performing hot restart...
Syncing files to device iPhone 12...
Restarted application in 368ms.
flutter: MyTest didPush: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/", [<'280748962'>], {}), animation: AnimationController#0adb5(⏭ 1.000; paused; for _PageBasedMaterialPageRoute<void>(/)))
flutter: MyTest didPush: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/login", [<'621841910'>], {}), animation: AnimationController#4775c(▶ 0.000; for _PageBasedMaterialPageRoute<void>(/login)))
flutter: MyTest didRemove: _PageBasedMaterialPageRoute<void>(MaterialPage<void>("/shop", [<'280748962'>], {}), animation: AnimationController#0adb5(⏭ 1.000; paused; for _PageBasedMaterialPageRoute<void>(/)))
Code sample
main.dart
void main() {
runApp(const MyApp());
}
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _shellNavigatorKey = GlobalKey<NavigatorState>();
final _router = GoRouter(
initialLocation: '/',
navigatorKey: _rootNavigatorKey,
observers: [
GoRouterObserver(),
],
routes: [
ShellRoute(
navigatorKey: _shellNavigatorKey,
builder: (context, state, child) {
return ScaffoldWithNavBar(child: child);
},
routes: [
GoRoute(
path: '/',
builder: (context, state) {
return const Home();
},
),
GoRoute(
path: '/discover',
builder: (context, state) {
return const Discover();
},
),
GoRoute(
path: '/shop',
builder: (context, state) {
return const Shop();
}),
],
),
GoRoute(
path: '/login',
builder: (context, state) {
return const Login();
},
),
],
);
class GoRouterObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
print('MyTest didPush: $route');
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
print('MyTest didPop: $route');
}
@override
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
print('MyTest didRemove: $route');
}
@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
print('MyTest didReplace: $newRoute');
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Platform',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routerConfig: _router,
);
}
}
scaffold_with_nav_bar.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class ScaffoldWithNavBar extends StatefulWidget {
const ScaffoldWithNavBar({super.key, required this.child});
final Widget child;
@override
State<ScaffoldWithNavBar> createState() => _ScaffoldWithNavBarState();
}
class _ScaffoldWithNavBarState extends State<ScaffoldWithNavBar> {
int _currentIndex = 0;
static const List<MyCustomBottomNavBarItem> tabs = [
MyCustomBottomNavBarItem(
icon: Icon(Icons.home),
activeIcon: Icon(Icons.home),
label: 'HOME',
initialLocation: '/',
),
MyCustomBottomNavBarItem(
icon: Icon(Icons.explore_outlined),
activeIcon: Icon(Icons.explore),
label: 'DISCOVER',
initialLocation: '/discover',
),
MyCustomBottomNavBarItem(
icon: Icon(Icons.storefront_outlined),
activeIcon: Icon(Icons.storefront),
label: 'SHOP',
initialLocation: '/shop',
),
MyCustomBottomNavBarItem(
icon: Icon(Icons.account_circle_outlined),
activeIcon: Icon(Icons.account_circle),
label: 'MY',
initialLocation: '/login',
),
];
@override
Widget build(BuildContext context) {
const labelStyle = TextStyle(fontFamily: 'Roboto');
return Scaffold(
body: SafeArea(child: widget.child),
bottomNavigationBar: BottomNavigationBar(
selectedLabelStyle: labelStyle,
unselectedLabelStyle: labelStyle,
selectedItemColor: const Color(0xFF434343),
selectedFontSize: 12,
unselectedItemColor: const Color(0xFF838383),
showUnselectedLabels: true,
type: BottomNavigationBarType.fixed,
onTap: (int index) {
_goOtherTab(context, index);
},
currentIndex: _currentIndex,
items: tabs,
),
);
}
void _goOtherTab(BuildContext context, int index) {
if (index == _currentIndex) return;
GoRouter router = GoRouter.of(context);
String location = tabs[index].initialLocation;
if (index == 3) {
router.push(location);
}
setState(() {
_currentIndex = index;
router.go(location);
});
}
}
class MyCustomBottomNavBarItem extends BottomNavigationBarItem {
final String initialLocation;
const MyCustomBottomNavBarItem(
{required this.initialLocation,
required Widget icon,
String? label,
Widget? activeIcon})
: super(icon: icon, label: label, activeIcon: activeIcon ?? icon);
}
Logs
info • Avoid `print` calls in production code • lib/main.dart:62:5 • avoid_print
info • Avoid `print` calls in production code • lib/main.dart:67:5 • avoid_print
info • Avoid `print` calls in production code • lib/main.dart:72:5 • avoid_print
info • Avoid `print` calls in production code • lib/main.dart:77:5 • avoid_print
info • Prefer const with constant constructors • lib/sections/discover/discover.dart:11:16 • prefer_const_constructors
info • Avoid using private types in public APIs • lib/sections/exhibition/detail_exhibition.dart:10:3 • library_private_types_in_public_api
info • Prefer const with constant constructors • lib/sections/exhibition/exhibition.dart:11:16 • prefer_const_constructors
info • Unused import: 'package:knowd_platform/sections/discover/discover.dart' • lib/sections/home/home.dart:2:8 • unused_import
info • Prefer const with constant constructors • lib/sections/home/home.dart:21:15 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/login/login.dart:11:16 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/login/login_router.dart:8:34 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/login/singup.dart:11:16 • prefer_const_constructors
info • Avoid using private types in public APIs • lib/sections/main_tab_bar.dart:12:3 • library_private_types_in_public_api
info • Private field could be final • lib/sections/main_tab_bar.dart:17:16 • prefer_final_fields
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:18:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:19:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:20:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:21:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:41:18 • prefer_const_constructors
info • Prefer const literals as parameters of constructors on @immutable classes • lib/sections/main_tab_bar.dart:59:17 • prefer_const_literals_to_create_immutables
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:60:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:61:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:64:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:65:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:68:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:69:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:72:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:73:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/shop.dart:10:16 • prefer_const_constructors
info • Avoid `print` calls in production code • lib/main.dart:62:5 • avoid_print
info • Avoid `print` calls in production code • lib/main.dart:67:5 • avoid_print
info • Avoid `print` calls in production code • lib/main.dart:72:5 • avoid_print
info • Avoid `print` calls in production code • lib/main.dart:77:5 • avoid_print
info • Prefer const with constant constructors • lib/sections/discover/discover.dart:11:16 • prefer_const_constructors
info • Avoid using private types in public APIs • lib/sections/exhibition/detail_exhibition.dart:10:3 • library_private_types_in_public_api
info • Prefer const with constant constructors • lib/sections/exhibition/exhibition.dart:11:16 • prefer_const_constructors
info • Unused import: 'package:knowd_platform/sections/discover/discover.dart' • lib/sections/home/home.dart:2:8 • unused_import
info • Prefer const with constant constructors • lib/sections/home/home.dart:21:15 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/login/login.dart:11:16 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/login/login_router.dart:8:34 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/login/singup.dart:11:16 • prefer_const_constructors
info • Avoid using private types in public APIs • lib/sections/main_tab_bar.dart:12:3 • library_private_types_in_public_api
info • Private field could be final • lib/sections/main_tab_bar.dart:17:16 • prefer_final_fields
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:18:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:19:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:20:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:21:5 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:41:18 • prefer_const_constructors
info • Prefer const literals as parameters of constructors on @immutable classes • lib/sections/main_tab_bar.dart:59:17 • prefer_const_literals_to_create_immutables
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:60:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:61:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:64:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:65:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:68:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:69:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:72:13 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/main_tab_bar.dart:73:21 • prefer_const_constructors
info • Prefer const with constant constructors • lib/sections/shop.dart:10:16 • prefer_const_constructors