@@ -152,6 +152,105 @@ For a complete example, see the [ShellRoute
152
152
sample] ( https://github.com/flutter/packages/tree/main/packages/go_router/example/lib/shell_route.dart )
153
153
in the example/ directory.
154
154
155
+ # Stateful nested navigation
156
+ In addition to using nested navigation with for instance a BottomNavigationBar,
157
+ many apps also require that state is maintained when navigating between
158
+ destinations. To accomplish this, use [ StatefulShellRoute] [ ] instead of
159
+ ` ShellRoute ` .
160
+
161
+ StatefulShellRoute creates separate ` Navigator ` s for each of its nested [ branches] ( https://pub.dev/documentation/go_router/latest/go_router/StatefulShellBranch-class.html )
162
+ (i.e. parallel navigation trees), making it possible to build an app with
163
+ stateful nested navigation. The constructor [ StatefulShellRoute.indexedStack] ( https://pub.dev/documentation/go_router/latest/go_router/StatefulShellRoute/StatefulShellRoute.indexedStack.html )
164
+ provides a default implementation for managing the branch navigators, using an
165
+ ` IndexedStack ` .
166
+
167
+ When using StatefulShellRoute, routes aren't configured on the shell route
168
+ itself. Instead, they are configured for each of the branches. Example:
169
+
170
+ <? code-excerpt "../example/lib/stateful_shell_route.dart (configuration-branches)"?>
171
+ ``` dart
172
+ branches: <StatefulShellBranch>[
173
+ // The route branch for the first tab of the bottom navigation bar.
174
+ StatefulShellBranch(
175
+ navigatorKey: _sectionANavigatorKey,
176
+ routes: <RouteBase>[
177
+ GoRoute(
178
+ // The screen to display as the root in the first tab of the
179
+ // bottom navigation bar.
180
+ path: '/a',
181
+ builder: (BuildContext context, GoRouterState state) =>
182
+ const RootScreen(label: 'A', detailsPath: '/a/details'),
183
+ routes: <RouteBase>[
184
+ // The details screen to display stacked on navigator of the
185
+ // first tab. This will cover screen A but not the application
186
+ // shell (bottom navigation bar).
187
+ GoRoute(
188
+ path: 'details',
189
+ builder: (BuildContext context, GoRouterState state) =>
190
+ const DetailsScreen(label: 'A'),
191
+ ),
192
+ ],
193
+ ),
194
+ ],
195
+ ),
196
+ ```
197
+
198
+ Similar to ShellRoute, a builder must be provided to build the actual shell
199
+ Widget that encapsulates the branch navigation container. The latter is
200
+ implemented by the class [ StatefulNavigationShell] ( https://pub.dev/documentation/go_router/latest/go_router/StatefulNavigationShell-class.html ) ,
201
+ which is passed as the last argument to the builder function. Example:
202
+
203
+ <? code-excerpt "../example/lib/stateful_shell_route.dart (configuration-builder)"?>
204
+ ``` dart
205
+ StatefulShellRoute.indexedStack(
206
+ builder: (BuildContext context, GoRouterState state,
207
+ StatefulNavigationShell navigationShell) {
208
+ // Return the widget that implements the custom shell (in this case
209
+ // using a BottomNavigationBar). The StatefulNavigationShell is passed
210
+ // to be able access the state of the shell and to navigate to other
211
+ // branches in a stateful way.
212
+ return ScaffoldWithNavBar(navigationShell: navigationShell);
213
+ },
214
+ ```
215
+
216
+ Within the custom shell widget, the StatefulNavigationShell is first and
217
+ foremost used as the child, or body, of the shell. Secondly, it is also used for
218
+ handling stateful switching between branches, as well as providing the currently
219
+ active branch index. Example:
220
+
221
+ <? code-excerpt "../example/lib/stateful_shell_route.dart (configuration-custom-shell)"?>
222
+ ``` dart
223
+ @override
224
+ Widget build(BuildContext context) {
225
+ return Scaffold(
226
+ // The StatefulNavigationShell from the associated StatefulShellRoute is
227
+ // directly passed as the body of the Scaffold.
228
+ body: navigationShell,
229
+ bottomNavigationBar: BottomNavigationBar(
230
+ // Here, the items of BottomNavigationBar are hard coded. In a real
231
+ // world scenario, the items would most likely be generated from the
232
+ // branches of the shell route, which can be fetched using
233
+ // `navigationShell.route.branches`.
234
+ items: const <BottomNavigationBarItem>[
235
+ BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Section A'),
236
+ BottomNavigationBarItem(icon: Icon(Icons.work), label: 'Section B'),
237
+ BottomNavigationBarItem(icon: Icon(Icons.tab), label: 'Section C'),
238
+ ],
239
+ currentIndex: navigationShell.currentIndex,
240
+ // Navigate to the current location of the branch at the provided index
241
+ // when tapping an item in the BottomNavigationBar.
242
+ onTap: (int index) => navigationShell.goBranch(index),
243
+ ),
244
+ );
245
+ }
246
+ ```
247
+
248
+ For a complete example, see the [ Stateful Nested
249
+ Navigation] ( https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/stateful_shell_route.dart )
250
+ in the example/ directory.
251
+ For further details, see the [ StatefulShellRoute API
252
+ documentation] ( https://pub.dev/documentation/go_router/latest/go_router/StatefulShellRoute-class.html ) .
253
+
155
254
# Initial location
156
255
157
256
The initial location is shown when the app first opens and there is no deep link
@@ -181,3 +280,4 @@ final _router = GoRouter(
181
280
[ GoRoute ] : https://pub.dev/documentation/go_router/latest/go_router/GoRoute-class.html
182
281
[ GoRouterState ] : https://pub.dev/documentation/go_router/latest/go_router/GoRouterState-class.html
183
282
[ ShellRoute ] : https://pub.dev/documentation/go_router/latest/go_router/ShellRoute-class.html
283
+ [ StatefulShellRoute ] : https://pub.dev/documentation/go_router/latest/go_router/StatefulShellRoute-class.html
0 commit comments