@@ -152,6 +152,105 @@ For a complete example, see the [ShellRoute
152152sample] ( https://github.com/flutter/packages/tree/main/packages/go_router/example/lib/shell_route.dart )
153153in the example/ directory.
154154
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+
155254# Initial location
156255
157256The initial location is shown when the app first opens and there is no deep link
@@ -181,3 +280,4 @@ final _router = GoRouter(
181280[ GoRoute ] : https://pub.dev/documentation/go_router/latest/go_router/GoRoute-class.html
182281[ GoRouterState ] : https://pub.dev/documentation/go_router/latest/go_router/GoRouterState-class.html
183282[ 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