Created
August 1, 2022 11:15
-
-
Save jonmountjoy/f36432a61a660dfd390c0b702df56ee8 to your computer and use it in GitHub Desktop.
Revisions
-
jonmountjoy created this gist
Aug 1, 2022 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,163 @@ 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, ); } }