Skip to content

Instantly share code, notes, and snippets.

@JohanScheepers
Last active February 4, 2025 14:20
Show Gist options
  • Save JohanScheepers/0164921fc4306a9ada7e0e3125cede06 to your computer and use it in GitHub Desktop.
Save JohanScheepers/0164921fc4306a9ada7e0e3125cede06 to your computer and use it in GitHub Desktop.
Riverpod Gorouter navigation
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'dart:async';
void main() {
runApp(const ProviderScope(child: HomeAutoApp()));
}
class HomeAutoApp extends StatelessWidget {
const HomeAutoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
routeInformationProvider: AppRoutes.router.routeInformationProvider,
routeInformationParser: AppRoutes.router.routeInformationParser,
routerDelegate: AppRoutes.router.routerDelegate,
);
}
}
//Splash Page
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
static const String route = "/splash";
@override
State<SplashPage> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
Timer durationTimer = Timer(Duration.zero, () {});
@override
void dispose() {
durationTimer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
durationTimer = Timer(Duration(seconds: 2), () {
GoRouter.of(Utils.mainNav.currentContext!).go(HomePage.route);
});
return Scaffold(
body: TextBoxDec(
text:
'Have you ever been asked to perform a task that would be easier or more efficient with a specialized tool or program?'));
}
}
//Main Page
class MainPage extends StatelessWidget {
final Widget child;
const MainPage({super.key, required this.child});
static const String route = "/main";
@override
Widget build(BuildContext context) {
return Scaffold(
body: Flex(
direction: Axis.vertical,
children: [
Expanded(
child: SafeArea(child: child),
),
const HomeAutomationBottomMenu()
],
),
);
}
}
//App Routes file
class AppRoutes {
static final router = GoRouter(
routerNeglect: true,
initialLocation: SplashPage.route,
navigatorKey: Utils.mainNav,
routes: [
GoRoute(
parentNavigatorKey: Utils.mainNav,
path: SplashPage.route,
builder: (context, state) {
return const SplashPage();
},
),
ShellRoute(
navigatorKey: Utils.tabNav,
builder: (context, state, child) {
return MainPage(child: child);
},
routes: [
GoRoute(
parentNavigatorKey: Utils.tabNav,
path: HomePage.route,
pageBuilder: (context, state) {
return const NoTransitionPage(
child: HomePage(),
);
},
),
GoRoute(
parentNavigatorKey: Utils.tabNav,
path: RoomsPage.route,
pageBuilder: (context, state) {
return const NoTransitionPage(
child: RoomsPage(),
);
},
),
GoRoute(
parentNavigatorKey: Utils.tabNav,
path: DevicesPage.route,
pageBuilder: (context, state) {
return const NoTransitionPage(
child: DevicesPage(),
);
},
),
GoRoute(
parentNavigatorKey: Utils.tabNav,
path: SettingsPage.route,
pageBuilder: (context, state) {
return const NoTransitionPage(
child: SettingsPage(),
);
},
),
]),
]);
}
//BottomBarMenuItem Model
class BottomBarMenuItemModel {
final IconData iconOption;
final String label;
final String route;
final bool isSelected;
const BottomBarMenuItemModel({
required this.iconOption,
this.label = '',
required this.route,
this.isSelected = false,
});
BottomBarMenuItemModel copyWith({
IconData? iconOption,
String? label,
String? route,
bool? isSelected,
}) {
return BottomBarMenuItemModel(
iconOption: iconOption ?? this.iconOption,
route: route ?? this.route,
label: label ?? this.label,
isSelected: isSelected ?? this.isSelected,
);
}
}
//PROVIDER
final bottomBarMenuProvider =
StateNotifierProvider<BottomBarMenuViewModel, List<BottomBarMenuItemModel>>(
(ref) {
final navItems = ref.read(bottomBarRepositoryProvider).getBottomBarNavItems();
return BottomBarMenuViewModel(navItems, ref);
});
final bottomBarRepositoryProvider = Provider((ref) {
return BottomMenuBarRepository();
});
//REPOSITORY
class BottomMenuBarRepository {
List<BottomBarMenuItemModel> getBottomBarNavItems() {
return const [
BottomBarMenuItemModel(
iconOption: Icons.home,
route: HomePage.route,
isSelected: true,
),
BottomBarMenuItemModel(
iconOption: Icons.door_back_door,
route: RoomsPage.route,
),
BottomBarMenuItemModel(
iconOption: Icons.devices,
route: DevicesPage.route,
),
BottomBarMenuItemModel(
iconOption: Icons.build,
route: SettingsPage.route,
)
];
}
}
//VIEW MODEL
class BottomBarMenuViewModel
extends StateNotifier<List<BottomBarMenuItemModel>> {
final Ref ref;
BottomBarMenuViewModel(super.state, this.ref);
void selectedItem(BottomBarMenuItemModel selectedItem) {
state = state.map((item) {
return item.copyWith(
isSelected: item.route == selectedItem.route,
);
}).toList();
GoRouter.of(Utils.tabNav.currentContext!).go(selectedItem.route);
}
}
//Bottom menu
class HomeAutomationBottomMenu extends ConsumerWidget {
const HomeAutomationBottomMenu({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final menuItems = ref.watch(bottomBarMenuProvider);
return Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: menuItems.map((e) {
return IconButton(
onPressed: () {
ref.read(bottomBarMenuProvider.notifier).selectedItem(e);
},
icon: Icon(
e.iconOption,
color: e.isSelected
? Theme.of(context).colorScheme.primary
: Theme.of(context).iconTheme.color,
));
}).toList());
}
}
// Home Page
class HomePage extends StatelessWidget {
const HomePage({super.key});
static const String route = '/home';
@override
Widget build(BuildContext context) {
return TextBoxDec(text: 'So, what were you looking for?');
}
}
//Rooms Page
class RoomsPage extends StatelessWidget {
const RoomsPage({super.key});
static const String route = '/room';
@override
Widget build(BuildContext context) {
return TextBoxDec(
text:
'We build software tailored to your unique business processes. Achieve maximum efficiency and unlock your full potential');
}
}
//Devices Page
class DevicesPage extends StatelessWidget {
const DevicesPage({super.key});
static const String route = '/devices';
@override
Widget build(BuildContext context) {
return TextBoxDec(text: 'Might be easier than you think');
}
}
//Settings Page
class SettingsPage extends StatelessWidget {
const SettingsPage({super.key});
static const String route = '/settings';
@override
Widget build(BuildContext context) {
return TextBoxDec(
text: 'Give us a call',
);
}
}
class TextBoxDec extends StatelessWidget {
const TextBoxDec({
super.key,
required this.text,
});
final String text;
@override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
width: 300,
height: 150,
child: DecoratedBox(
decoration: BoxDecoration(
color: Colors.lightGreen,
borderRadius: BorderRadius.circular(15),
border: Border.all(width: 5, color: Colors.blue)),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Center(child: Text(text)),
),
),
),
);
}
}
//Utils file
class Utils {
static final mainNav = GlobalKey<NavigatorState>();
static final tabNav = GlobalKey<NavigatorState>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment