Skip to content

Instantly share code, notes, and snippets.

@jonmountjoy
Created August 1, 2022 11:15
Show Gist options
  • Save jonmountjoy/f36432a61a660dfd390c0b702df56ee8 to your computer and use it in GitHub Desktop.
Save jonmountjoy/f36432a61a660dfd390c0b702df56ee8 to your computer and use it in GitHub Desktop.
routing
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
// The data we display
class Family {
int id;
String name;
Family(this.id, this.name);
}
class Families {
static List<Family> data = [
Family(1, "Foxtrot"),
Family(2, "Lima"),
];
}
// How we display a family
class FamilyView extends StatelessWidget {
final Family family;
const FamilyView({required this.family});
@override
Widget build(BuildContext context) {
return Column(children: [
Text(family.name),
TextButton(child: Text("Go to /f1"), onPressed: () => context.go("/f1")),
TextButton(child: Text("Go to /family/1"), onPressed: () => context.go("/family/1")),
]);
}
}
// The tab screen, that I'd like to avoid rebuilding
class FamilyTabsScreen extends StatefulWidget {
final int index;
// If true, don't use a "path-based family" for the
// destination. ie. instead of /family/1 go to /f1
final bool alternative;
FamilyTabsScreen(
{required Family currentFamily, required this.alternative, Key? key})
: index = Families.data.indexWhere((f) => f.id == currentFamily.id),
super(key: key) {
assert(index != -1);
}
@override
State<FamilyTabsScreen> createState() => _FamilyTabsScreenState();
}
class _FamilyTabsScreenState extends State<FamilyTabsScreen>
with TickerProviderStateMixin {
late final TabController _controller;
@override
void initState() {
super.initState();
_controller = TabController(
length: Families.data.length,
vsync: this,
initialIndex: widget.index,
);
}
@override
void dispose() {
_controller.dispose();
print("FamilyTabScreen: Dispose");
super.dispose();
}
@override
void didUpdateWidget(FamilyTabsScreen oldWidget) {
super.didUpdateWidget(oldWidget);
print("FamilyTabScreen: Did Update Widget");
_controller.index = widget.index;
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text(_title(context)),
bottom: TabBar(
controller: _controller,
tabs: [for (final f in Families.data) Tab(text: f.name)],
onTap: (index) => _tap(context, index),
),
),
body: TabBarView(
controller: _controller,
children: [for (final f in Families.data) FamilyView(family: f)],
),
);
void _tap(BuildContext context, int index) => widget.alternative
? context.go('/f${Families.data[index].id}')
: context.go('/family/${Families.data[index].id}');
String _title(BuildContext context) =>
(context as Element).findAncestorWidgetOfExactType<MaterialApp>()!.title;
}
var sharedKey = ValueKey("sharedRoute");
final _router = GoRouter(
routes: [
GoRoute(
path: '/',
redirect: (_) => '/family/${Families.data[0].id}',
),
GoRoute(
path: '/family/:fid',
builder: (context, state) {
print(sharedKey);
final fid = int.parse(state.params['fid']!);
final family = Families.data.firstWhere((f) => f.id == fid,
orElse: () => throw Exception('family not found: $fid'));
return FamilyTabsScreen(
key: sharedKey, currentFamily: family, alternative: false);
},
),
GoRoute(
path: '/f1',
builder: (context, state) {
print(sharedKey);
final family = Families.data.firstWhere((f) => f.id == 1);
return FamilyTabsScreen(
key: sharedKey, currentFamily: family, alternative: true);
},
),
GoRoute(
path: '/f2',
builder: (context, state) {
final family = Families.data.firstWhere((f) => f.id == 2);
return FamilyTabsScreen(
key: sharedKey, currentFamily: family, alternative: true);
},
),
],
);
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
routeInformationParser: _router.routeInformationParser,
routerDelegate: _router.routerDelegate,
routeInformationProvider: _router.routeInformationProvider,
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment