Add base skeleton
This commit is contained in:
100
moneymgr_mobile/lib/widgets/scaffold_with_navigation.dart
Normal file
100
moneymgr_mobile/lib/widgets/scaffold_with_navigation.dart
Normal file
@ -0,0 +1,100 @@
|
||||
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 [],
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user