Jonny Borges
Committed by GitHub

Merge pull request #2898 from jonataslaw/indexed_route

add IndexedRouteBuild to make nested routes easier
@@ -6,65 +6,61 @@ import '../controllers/home_controller.dart'; @@ -6,65 +6,61 @@ import '../controllers/home_controller.dart';
6 6
7 class HomeView extends GetView<HomeController> { 7 class HomeView extends GetView<HomeController> {
8 const HomeView({Key? key}) : super(key: key); 8 const HomeView({Key? key}) : super(key: key);
  9 +
9 @override 10 @override
10 Widget build(BuildContext context) { 11 Widget build(BuildContext context) {
11 - return GetRouterOutlet.builder(  
12 - routerDelegate: Get.nestedKey(Routes.home),  
13 - builder: (context) {  
14 - final delegate = context.navigation;  
15 - //This router outlet handles the appbar and the bottom navigation bar  
16 - final currentLocation = context.location;  
17 - var currentIndex = 0;  
18 - if (currentLocation.startsWith(Routes.products) == true) {  
19 - currentIndex = 2;  
20 - }  
21 - if (currentLocation.startsWith(Routes.profile) == true) {  
22 - currentIndex = 1;  
23 - }  
24 - return Scaffold(  
25 - body: GetRouterOutlet(  
26 - initialRoute: Routes.dashboard,  
27 - anchorRoute: Routes.home,  
28 -  
29 - //delegate: Get.nestedKey(Routes.HOME),  
30 - // key: Get.nestedKey(Routes.HOME),  
31 - ),  
32 - bottomNavigationBar: BottomNavigationBar(  
33 - currentIndex: currentIndex,  
34 - onTap: (value) {  
35 - switch (value) {  
36 - case 0:  
37 - delegate.toNamed(Routes.home);  
38 - break;  
39 - case 1:  
40 - delegate.toNamed(Routes.profile);  
41 - break;  
42 - case 2:  
43 - delegate.toNamed(Routes.products);  
44 - break;  
45 - default:  
46 - } 12 + return Column(
  13 + children: [
  14 + Container(
  15 + color: Colors.yellow,
  16 + width: double.infinity,
  17 + height: 25,
  18 + ),
  19 + Expanded(
  20 + child: GetRouterOutlet.builder(
  21 + route: Routes.home,
  22 + builder: (context) {
  23 + return Scaffold(
  24 + body: GetRouterOutlet(
  25 + initialRoute: Routes.dashboard,
  26 + anchorRoute: Routes.home,
  27 + ),
  28 + bottomNavigationBar: IndexedRouteBuilder(
  29 + routes: const [
  30 + Routes.dashboard,
  31 + Routes.profile,
  32 + Routes.products
  33 + ],
  34 + builder: (context, routes, index) {
  35 + final delegate = context.delegate;
  36 + return BottomNavigationBar(
  37 + currentIndex: index,
  38 + onTap: (value) => delegate.toNamed(routes[value]),
  39 + items: const [
  40 + // _Paths.HOME + [Empty]
  41 + BottomNavigationBarItem(
  42 + icon: Icon(Icons.home),
  43 + label: 'Home',
  44 + ),
  45 + // _Paths.HOME + Routes.PROFILE
  46 + BottomNavigationBarItem(
  47 + icon: Icon(Icons.account_box_rounded),
  48 + label: 'Profile',
  49 + ),
  50 + // _Paths.HOME + _Paths.PRODUCTS
  51 + BottomNavigationBarItem(
  52 + icon: Icon(Icons.account_box_rounded),
  53 + label: 'Products',
  54 + ),
  55 + ],
  56 + );
  57 + }),
  58 + );
47 }, 59 },
48 - items: const [  
49 - // _Paths.HOME + [Empty]  
50 - BottomNavigationBarItem(  
51 - icon: Icon(Icons.home),  
52 - label: 'Home',  
53 - ),  
54 - // _Paths.HOME + Routes.PROFILE  
55 - BottomNavigationBarItem(  
56 - icon: Icon(Icons.account_box_rounded),  
57 - label: 'Profile',  
58 - ),  
59 - // _Paths.HOME + _Paths.PRODUCTS  
60 - BottomNavigationBarItem(  
61 - icon: Icon(Icons.account_box_rounded),  
62 - label: 'Products',  
63 - ),  
64 - ],  
65 ), 60 ),
66 - );  
67 - }, 61 + ),
  62 + ],
68 ); 63 );
69 } 64 }
70 } 65 }
  66 +
@@ -43,11 +43,9 @@ extension PageArgExt on BuildContext { @@ -43,11 +43,9 @@ extension PageArgExt on BuildContext {
43 return parser?.restoreRouteInformation(config)?.location ?? '/'; 43 return parser?.restoreRouteInformation(config)?.location ?? '/';
44 } 44 }
45 45
46 - RouterDelegate get delegate {  
47 - return router.routerDelegate;  
48 - }  
49 46
50 - GetDelegate get navigation { 47 +
  48 + GetDelegate get delegate {
51 return router.routerDelegate as GetDelegate; 49 return router.routerDelegate as GetDelegate;
52 } 50 }
53 } 51 }
@@ -234,7 +234,7 @@ class PageRedirect { @@ -234,7 +234,7 @@ class PageRedirect {
234 if (settings == null && route != null) { 234 if (settings == null && route != null) {
235 settings = route; 235 settings = route;
236 } 236 }
237 - final match = context.navigation.matchRoute(settings!.name!); 237 + final match = context.delegate.matchRoute(settings!.name!);
238 Get.parameters = match.parameters; 238 Get.parameters = match.parameters;
239 239
240 // No Match found 240 // No Match found
@@ -148,10 +148,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> { @@ -148,10 +148,14 @@ class GetRouterOutlet extends RouterOutlet<GetDelegate, RouteDecoder> {
148 required Widget Function( 148 required Widget Function(
149 BuildContext context, 149 BuildContext context,
150 ) builder, 150 ) builder,
  151 + String? route,
151 GetDelegate? routerDelegate, 152 GetDelegate? routerDelegate,
152 }) : super.builder( 153 }) : super.builder(
153 builder: builder, 154 builder: builder,
154 - delegate: routerDelegate, 155 + delegate: routerDelegate ??
  156 + (route != null
  157 + ? Get.nestedKey(route)
  158 + : Get.rootController.rootDelegate),
155 ); 159 );
156 } 160 }
157 161
@@ -166,3 +170,54 @@ extension PagesListExt on List<GetPage> { @@ -166,3 +170,54 @@ extension PagesListExt on List<GetPage> {
166 return pickAtRoute(route).skip(1); 170 return pickAtRoute(route).skip(1);
167 } 171 }
168 } 172 }
  173 +
  174 +class GetRouterOutletInherited extends InheritedWidget {
  175 + final String anchorRoute;
  176 +
  177 + const GetRouterOutletInherited({
  178 + super.key,
  179 + required this.anchorRoute,
  180 + required Widget child,
  181 + }) : super(child: child);
  182 +
  183 + static GetRouterOutletInherited? of(BuildContext context) {
  184 + return context
  185 + .dependOnInheritedWidgetOfExactType<GetRouterOutletInherited>();
  186 + }
  187 +
  188 + @override
  189 + bool updateShouldNotify(covariant InheritedWidget oldWidget) {
  190 + return true;
  191 + }
  192 +}
  193 +
  194 +typedef NavigatorItemBuilderBuilder = Widget Function(
  195 + BuildContext context, List<String> routes, int index);
  196 +
  197 +class IndexedRouteBuilder<T> extends StatelessWidget {
  198 + const IndexedRouteBuilder({
  199 + Key? key,
  200 + required this.builder,
  201 + required this.routes,
  202 + }) : super(key: key);
  203 + final List<String> routes;
  204 + final NavigatorItemBuilderBuilder builder;
  205 +
  206 +// Method to get the current index based on the route
  207 + int _getCurrentIndex(String currentLocation) {
  208 + for (int i = 0; i < routes.length; i++) {
  209 + if (currentLocation.startsWith(routes[i])) {
  210 + return i;
  211 + }
  212 + }
  213 + return 0; // default index
  214 + }
  215 +
  216 + @override
  217 + Widget build(BuildContext context) {
  218 + final location = context.location;
  219 + final index = _getCurrentIndex(location);
  220 +
  221 + return builder(context, routes, index);
  222 + }
  223 +}