Skip to content

Instantly share code, notes, and snippets.

@jonmountjoy
Created August 1, 2022 11:15
Show Gist options
  • Select an option

  • Save jonmountjoy/f36432a61a660dfd390c0b702df56ee8 to your computer and use it in GitHub Desktop.

Select an option

Save jonmountjoy/f36432a61a660dfd390c0b702df56ee8 to your computer and use it in GitHub Desktop.

Revisions

  1. jonmountjoy created this gist Aug 1, 2022.
    163 changes: 163 additions & 0 deletions main.dart
    Original 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,
    );
    }
    }