Skip to content
This repository was archived by the owner on May 14, 2023. It is now read-only.

Commit ee6e80e

Browse files
authored
Add NavigationType and overridable Resolver function to configure how the component adapts to different navigation configurations. (#58)
* Add NavigationType and overridable resolver function * clarify comments for resolving to specific navigation types * rami comments * typos * rami comments * Remove divider color
1 parent 8d17469 commit ee6e80e

File tree

2 files changed

+103
-86
lines changed

2 files changed

+103
-86
lines changed

example/lib/main.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import 'package:flutter/material.dart';
2-
import 'package:adaptive_navigation_scaffold/scaffold.dart';
2+
import 'package:adaptive_navigation/scaffold.dart';
33

44
void main() {
55
runApp(MyApp());
66
}
77

88
class MyApp extends StatelessWidget {
9-
// This widget is the root of your application.
109
@override
1110
Widget build(BuildContext context) {
1211
return MaterialApp(

lib/scaffold.dart

Lines changed: 102 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44

55
import 'package:flutter/material.dart';
66

7-
bool _isLargeScreen(BuildContext context) {
8-
return MediaQuery.of(context).size.width > 960.0;
9-
}
7+
typedef NavigationType NavigationTypeResolver(BuildContext context);
108

11-
bool _isMediumScreen(BuildContext context) {
12-
return MediaQuery.of(context).size.width > 640.0;
9+
// The type of navigation to configure to.
10+
enum NavigationType {
11+
bottomNavigation,
12+
navigationRail,
13+
drawer,
1314
}
1415

1516
/// See bottomNavigationBarItem or NavigationRailDestination
@@ -34,6 +35,7 @@ class AdaptiveNavigationScaffold extends StatefulWidget {
3435
final List<AdaptiveScaffoldDestination> destinations;
3536
final ValueChanged<int> onNavigationIndexChange;
3637
final FloatingActionButton floatingActionButton;
38+
final NavigationTypeResolver navigationTypeResolver;
3739

3840
AdaptiveNavigationScaffold({
3941
this.title,
@@ -42,6 +44,7 @@ class AdaptiveNavigationScaffold extends StatefulWidget {
4244
@required this.destinations,
4345
this.onNavigationIndexChange,
4446
this.floatingActionButton,
47+
this.navigationTypeResolver,
4548
}) : assert(currentIndex != null),
4649
assert(destinations != null);
4750

@@ -52,105 +55,120 @@ class AdaptiveNavigationScaffold extends StatefulWidget {
5255

5356
class _AdaptiveNavigationScaffoldState
5457
extends State<AdaptiveNavigationScaffold> {
58+
NavigationType _defaultNavigationTypeResolver(BuildContext context) {
59+
if (_isLargeScreen(context)) {
60+
return NavigationType.drawer;
61+
} else if (_isMediumScreen(context)) {
62+
return NavigationType.navigationRail;
63+
} else {
64+
return NavigationType.bottomNavigation;
65+
}
66+
}
67+
5568
@override
5669
Widget build(BuildContext context) {
57-
// Show a Drawer
58-
if (_isLargeScreen(context)) {
59-
return Row(
60-
children: [
61-
Drawer(
62-
child: Column(
63-
children: [
64-
DrawerHeader(
65-
child: Center(
66-
child: widget.title,
67-
),
70+
final NavigationTypeResolver navigationTypeResolver =
71+
widget.navigationTypeResolver ?? _defaultNavigationTypeResolver;
72+
switch (navigationTypeResolver(context)) {
73+
case NavigationType.bottomNavigation:
74+
// Show a Scaffold with a BottomNavigationBar.
75+
return Scaffold(
76+
body: widget.body,
77+
appBar: AppBar(title: widget.title),
78+
bottomNavigationBar: BottomNavigationBar(
79+
items: [
80+
for (final destination in widget.destinations)
81+
BottomNavigationBarItem(
82+
icon: Icon(destination.icon),
83+
title: Text(destination.title),
6884
),
69-
for (var d in widget.destinations)
70-
ListTile(
71-
leading: Icon(d.icon),
72-
title: Text(d.title),
73-
selected:
74-
widget.destinations.indexOf(d) == widget.currentIndex,
75-
onTap: () => _destinationTapped(d),
76-
),
77-
],
78-
),
85+
],
86+
currentIndex: widget.currentIndex,
87+
onTap: widget.onNavigationIndexChange,
7988
),
80-
VerticalDivider(
81-
width: 1,
82-
thickness: 1,
83-
color: Colors.grey[300],
89+
floatingActionButton: widget.floatingActionButton,
90+
);
91+
case NavigationType.navigationRail:
92+
// Show a Scaffold with a body containing a NavigationRail.
93+
return Scaffold(
94+
appBar: AppBar(
95+
title: widget.title,
8496
),
85-
Expanded(
86-
child: Scaffold(
87-
appBar: AppBar(),
88-
body: widget.body,
89-
floatingActionButton: widget.floatingActionButton,
90-
),
97+
body: Row(
98+
children: [
99+
NavigationRail(
100+
leading: widget.floatingActionButton,
101+
destinations: [
102+
for (final destination in widget.destinations)
103+
NavigationRailDestination(
104+
icon: Icon(destination.icon),
105+
label: Text(destination.title),
106+
),
107+
],
108+
selectedIndex: widget.currentIndex,
109+
onDestinationSelected: widget.onNavigationIndexChange ?? (_) {},
110+
),
111+
VerticalDivider(
112+
width: 1,
113+
thickness: 1,
114+
),
115+
Expanded(
116+
child: widget.body,
117+
),
118+
],
91119
),
92-
],
93-
);
94-
}
95-
96-
// Show a navigation rail
97-
if (_isMediumScreen(context)) {
98-
return Scaffold(
99-
appBar: AppBar(
100-
title: widget.title,
101-
),
102-
body: Row(
120+
);
121+
case NavigationType.drawer:
122+
// Show a Row containing a Drawer and Scaffold.
123+
return Row(
103124
children: [
104-
NavigationRail(
105-
leading: widget.floatingActionButton,
106-
destinations: [
107-
...widget.destinations.map(
108-
(d) => NavigationRailDestination(
109-
icon: Icon(d.icon),
110-
label: Text(d.title),
125+
Drawer(
126+
child: Column(
127+
children: [
128+
DrawerHeader(
129+
child: Center(
130+
child: widget.title,
131+
),
111132
),
112-
),
113-
],
114-
selectedIndex: widget.currentIndex,
115-
onDestinationSelected: widget.onNavigationIndexChange ?? (_) {},
133+
for (final destination in widget.destinations)
134+
ListTile(
135+
leading: Icon(destination.icon),
136+
title: Text(destination.title),
137+
selected: widget.destinations.indexOf(destination) ==
138+
widget.currentIndex,
139+
onTap: () => _destinationTapped(destination),
140+
),
141+
],
142+
),
116143
),
117144
VerticalDivider(
118145
width: 1,
119146
thickness: 1,
120-
color: Colors.grey[300],
121147
),
122148
Expanded(
123-
child: widget.body,
149+
child: Scaffold(
150+
appBar: AppBar(),
151+
body: widget.body,
152+
floatingActionButton: widget.floatingActionButton,
153+
),
124154
),
125155
],
126-
),
127-
);
156+
);
128157
}
129-
130-
// Show a bottom app bar
131-
return Scaffold(
132-
body: widget.body,
133-
appBar: AppBar(title: widget.title),
134-
bottomNavigationBar: BottomNavigationBar(
135-
items: [
136-
...widget.destinations.map(
137-
(d) => BottomNavigationBarItem(
138-
icon: Icon(d.icon),
139-
title: Text(d.title),
140-
),
141-
),
142-
],
143-
currentIndex: widget.currentIndex,
144-
onTap: widget.onNavigationIndexChange,
145-
),
146-
floatingActionButton: widget.floatingActionButton,
147-
);
148158
}
149159

150160
void _destinationTapped(AdaptiveScaffoldDestination destination) {
151-
var idx = widget.destinations.indexOf(destination);
152-
if (idx != widget.currentIndex) {
153-
widget.onNavigationIndexChange(idx);
161+
final index = widget.destinations.indexOf(destination);
162+
if (index != widget.currentIndex) {
163+
widget.onNavigationIndexChange(index);
154164
}
155165
}
156166
}
167+
168+
bool _isLargeScreen(BuildContext context) {
169+
return MediaQuery.of(context).size.width > 960.0;
170+
}
171+
172+
bool _isMediumScreen(BuildContext context) {
173+
return MediaQuery.of(context).size.width > 640.0;
174+
}

0 commit comments

Comments
 (0)