Skip to content

Commit 02a950b

Browse files
authored
Add responsive nested navigation with NaviationBar, NavigationRail (bizz84#138)
1 parent ea98d1c commit 02a950b

File tree

3 files changed

+137
-53
lines changed

3 files changed

+137
-53
lines changed

lib/src/routing/app_router.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import 'package:starter_architecture_flutter_firebase/src/features/jobs/presenta
1414
import 'package:starter_architecture_flutter_firebase/src/features/onboarding/data/onboarding_repository.dart';
1515
import 'package:starter_architecture_flutter_firebase/src/features/onboarding/presentation/onboarding_screen.dart';
1616
import 'package:starter_architecture_flutter_firebase/src/routing/go_router_refresh_stream.dart';
17-
import 'package:starter_architecture_flutter_firebase/src/routing/scaffold_with_bottom_nav_bar.dart';
17+
import 'package:starter_architecture_flutter_firebase/src/routing/scaffold_with_nested_navigation.dart';
1818

1919
part 'app_router.g.dart';
2020

@@ -90,7 +90,7 @@ GoRouter goRouter(GoRouterRef ref) {
9090
// https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/stateful_shell_route.dart
9191
StatefulShellRoute.indexedStack(
9292
builder: (context, state, navigationShell) {
93-
return ScaffoldWithBottomNavBar(navigationShell: navigationShell);
93+
return ScaffoldWithNestedNavigation(navigationShell: navigationShell);
9494
},
9595
branches: [
9696
StatefulShellBranch(

lib/src/routing/scaffold_with_bottom_nav_bar.dart

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// ignore_for_file: public_member_api_docs, sort_constructors_first
2+
import 'package:flutter/material.dart';
3+
import 'package:go_router/go_router.dart';
4+
5+
import 'package:starter_architecture_flutter_firebase/src/localization/string_hardcoded.dart';
6+
7+
// Stateful navigation based on:
8+
// https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/stateful_shell_route.dart
9+
class ScaffoldWithNestedNavigation extends StatelessWidget {
10+
const ScaffoldWithNestedNavigation({
11+
Key? key,
12+
required this.navigationShell,
13+
}) : super(
14+
key: key ?? const ValueKey<String>('ScaffoldWithNestedNavigation'));
15+
final StatefulNavigationShell navigationShell;
16+
17+
void _goBranch(int index) {
18+
navigationShell.goBranch(
19+
index,
20+
// A common pattern when using bottom navigation bars is to support
21+
// navigating to the initial location when tapping the item that is
22+
// already active. This example demonstrates how to support this behavior,
23+
// using the initialLocation parameter of goBranch.
24+
initialLocation: index == navigationShell.currentIndex,
25+
);
26+
}
27+
28+
@override
29+
Widget build(BuildContext context) {
30+
final size = MediaQuery.sizeOf(context);
31+
if (size.width < 450) {
32+
return ScaffoldWithBottomNavBar(
33+
body: navigationShell,
34+
currentIndex: navigationShell.currentIndex,
35+
onDestinationSelected: _goBranch,
36+
);
37+
} else {
38+
return ScaffoldWithNavigationRail(
39+
body: navigationShell,
40+
currentIndex: navigationShell.currentIndex,
41+
onDestinationSelected: _goBranch,
42+
);
43+
}
44+
}
45+
}
46+
47+
class ScaffoldWithBottomNavBar extends StatelessWidget {
48+
const ScaffoldWithBottomNavBar({
49+
super.key,
50+
required this.body,
51+
required this.currentIndex,
52+
required this.onDestinationSelected,
53+
});
54+
final Widget body;
55+
final int currentIndex;
56+
final ValueChanged<int> onDestinationSelected;
57+
58+
@override
59+
Widget build(BuildContext context) {
60+
return Scaffold(
61+
body: body,
62+
bottomNavigationBar: NavigationBar(
63+
selectedIndex: currentIndex,
64+
destinations: [
65+
// products
66+
NavigationDestination(
67+
icon: const Icon(Icons.work_outline),
68+
selectedIcon: const Icon(Icons.work),
69+
label: 'Jobs'.hardcoded,
70+
),
71+
NavigationDestination(
72+
icon: const Icon(Icons.view_headline_outlined),
73+
selectedIcon: const Icon(Icons.view_headline),
74+
label: 'Entries'.hardcoded,
75+
),
76+
NavigationDestination(
77+
icon: const Icon(Icons.person_outline),
78+
selectedIcon: const Icon(Icons.person),
79+
label: 'Account'.hardcoded,
80+
),
81+
],
82+
onDestinationSelected: onDestinationSelected,
83+
),
84+
);
85+
}
86+
}
87+
88+
class ScaffoldWithNavigationRail extends StatelessWidget {
89+
const ScaffoldWithNavigationRail({
90+
super.key,
91+
required this.body,
92+
required this.currentIndex,
93+
required this.onDestinationSelected,
94+
});
95+
final Widget body;
96+
final int currentIndex;
97+
final ValueChanged<int> onDestinationSelected;
98+
99+
@override
100+
Widget build(BuildContext context) {
101+
return Scaffold(
102+
body: Row(
103+
children: [
104+
NavigationRail(
105+
selectedIndex: currentIndex,
106+
onDestinationSelected: onDestinationSelected,
107+
labelType: NavigationRailLabelType.all,
108+
destinations: <NavigationRailDestination>[
109+
NavigationRailDestination(
110+
icon: const Icon(Icons.work_outline),
111+
selectedIcon: const Icon(Icons.work),
112+
label: Text('Jobs'.hardcoded),
113+
),
114+
NavigationRailDestination(
115+
icon: const Icon(Icons.view_headline_outlined),
116+
selectedIcon: const Icon(Icons.view_headline),
117+
label: Text('Entries'.hardcoded),
118+
),
119+
NavigationRailDestination(
120+
icon: const Icon(Icons.person_outline),
121+
selectedIcon: const Icon(Icons.person),
122+
label: Text('Account'.hardcoded),
123+
),
124+
],
125+
),
126+
const VerticalDivider(thickness: 1, width: 1),
127+
// This is the main content.
128+
Expanded(
129+
child: body,
130+
),
131+
],
132+
),
133+
);
134+
}
135+
}

0 commit comments

Comments
 (0)