101 lines
2.8 KiB
Dart
101 lines
2.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
|
|
/// A scaffold that shows navigation bar/rail when the current path is a navigation
|
|
/// item.
|
|
///
|
|
/// When in a navigation item, a [NavigationBar] will be shown if the width of the
|
|
/// screen is less than 600dp. Otherwise, a [NavigationRail] will be shown.
|
|
class ScaffoldWithNavigation extends StatelessWidget {
|
|
const ScaffoldWithNavigation({
|
|
super.key,
|
|
required this.child,
|
|
required this.selectedIndex,
|
|
required this.navigationItems,
|
|
});
|
|
|
|
final Widget child;
|
|
final int selectedIndex;
|
|
final List<NavigationItem> navigationItems;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
void onDestinationSelected(int index) =>
|
|
context.go(navigationItems[index].path);
|
|
|
|
// Use navigation rail instead of navigation bar when the screen width is
|
|
// larger than 600dp.
|
|
if (MediaQuery.sizeOf(context).width > 600) {
|
|
return Scaffold(
|
|
body: Row(
|
|
children: [
|
|
NavigationRail(
|
|
selectedIndex: selectedIndex,
|
|
onDestinationSelected: onDestinationSelected,
|
|
destinations: [
|
|
for (final item in navigationItems)
|
|
NavigationRailDestination(
|
|
icon: Icon(item.icon),
|
|
selectedIcon: item.selectedIcon != null
|
|
? Icon(item.selectedIcon)
|
|
: null,
|
|
label: Text(item.label),
|
|
)
|
|
],
|
|
extended: true,
|
|
),
|
|
Expanded(child: child),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
return Scaffold(
|
|
body: child,
|
|
bottomNavigationBar: NavigationBar(
|
|
selectedIndex: selectedIndex,
|
|
onDestinationSelected: onDestinationSelected,
|
|
destinations: [
|
|
for (final item in navigationItems)
|
|
NavigationDestination(
|
|
icon: Icon(item.icon),
|
|
selectedIcon:
|
|
item.selectedIcon != null ? Icon(item.selectedIcon) : null,
|
|
label: item.label,
|
|
)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// An item that represents a navigation destination in a navigation bar/rail.
|
|
class NavigationItem {
|
|
/// Path in the router.
|
|
final String path;
|
|
|
|
/// Widget to show when navigating to this [path].
|
|
final WidgetBuilder body;
|
|
|
|
/// Icon in the navigation bar.
|
|
final IconData icon;
|
|
|
|
/// Icon in the navigation bar when selected.
|
|
final IconData? selectedIcon;
|
|
|
|
/// Label in the navigation bar.
|
|
final String label;
|
|
|
|
/// The subroutes of the route from this [path].
|
|
final List<RouteBase> routes;
|
|
|
|
NavigationItem({
|
|
required this.path,
|
|
required this.body,
|
|
required this.icon,
|
|
this.selectedIcon,
|
|
required this.label,
|
|
this.routes = const [],
|
|
});
|
|
}
|