Skip to content

Instantly share code, notes, and snippets.

@SEGVeenstra
Last active September 24, 2024 18:17
Show Gist options
  • Save SEGVeenstra/0b1afa02bc35f4afe34b76951c10b94b to your computer and use it in GitHub Desktop.
Save SEGVeenstra/0b1afa02bc35f4afe34b76951c10b94b to your computer and use it in GitHub Desktop.
GoRouter - reusable routes
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
routerConfig: myRouter,
);
}
}
class MyTabPage extends StatelessWidget {
const MyTabPage({
required this.child,
super.key,
});
final Widget child;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(Icons.person),
onPressed: () {
print(context.currentPath);
GoRouter.of(context).go(
context.currentPath == '/list' ? '/list/account' : '/account',
);
},
),
],
),
body: child,
bottomNavigationBar: NavigationBar(
selectedIndex: context.currentPath.startsWith('/list') ? 1 : 0,
onDestinationSelected: (index) {
if (index == 0) GoRouter.of(context).go('/');
if (index == 1) GoRouter.of(context).go('/list');
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.home),
label: 'Home',
),
NavigationDestination(
icon: Icon(Icons.list),
label: 'Items',
),
],
),
);
}
}
class MyTabContent extends StatelessWidget {
const MyTabContent({
required this.name,
super.key,
});
final String name;
@override
Widget build(BuildContext context) {
return Center(
child: Text(name),
);
}
}
class AccountPage extends StatelessWidget {
const AccountPage({
required this.name,
super.key,
this.hasSubButton = false,
});
final String name;
final bool hasSubButton;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey,
appBar: AppBar(),
body: Center(
child: Column(
children: [
Text(name),
if (hasSubButton)
ElevatedButton(
onPressed: () =>
GoRouter.of(context).go(context.currentPath + '/sub'),
child: Text('Sub page'),
),
],
),
),
);
}
}
final rootKey = GlobalKey<NavigatorState>();
final tabKey = GlobalKey<NavigatorState>();
final myRouter = GoRouter(
routes: mainRoutes,
navigatorKey: rootKey,
);
final mainRoutes = [
ShellRoute(
navigatorKey: tabKey,
builder: (context, state, child) => MyTabPage(child: child),
routes: [
GoRoute(
path: '/',
builder: (context, state) => const MyTabContent(name: 'Home'),
routes: [
accountsRoute,
],
),
GoRoute(
path: '/list',
builder: (context, state) => const MyTabContent(name: 'List'),
routes: [
accountsRoute,
],
),
],
),
];
// This is the trick.
// You can just create a full configured sub-tree.
final accountsRoute = GoRoute(
parentNavigatorKey: rootKey,
path: 'account',
builder: (context, state) => AccountPage(
name: 'Account',
hasSubButton: true,
),
routes: [
GoRoute(
parentNavigatorKey: rootKey,
path: 'sub',
builder: (context, state) => AccountPage(
name: 'sub',
),
),
],
);
extension on BuildContext {
String get currentPath =>
GoRouter.of(this).routeInformationProvider.value.uri.path;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment