Created
August 1, 2022 11:15
-
-
Save jonmountjoy/f36432a61a660dfd390c0b702df56ee8 to your computer and use it in GitHub Desktop.
routing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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