blob: a762e12c1241d05f9699f8c851546fc45a93d5a7 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: public_member_api_docs, unreachable_from_main
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
part 'shell_route_with_observers_example.g.dart';
void main() => runApp(App());
class App extends StatelessWidget {
App({super.key});
@override
Widget build(BuildContext context) => MaterialApp.router(
routerConfig: _router,
);
final GoRouter _router = GoRouter(
routes: $appRoutes,
initialLocation: '/home',
);
}
@TypedShellRoute<MyShellRouteData>(
routes: <TypedRoute<RouteData>>[
TypedGoRoute<HomeRouteData>(path: '/home'),
TypedGoRoute<UsersRouteData>(
path: '/users',
routes: <TypedGoRoute<UserRouteData>>[
TypedGoRoute<UserRouteData>(path: ':id'),
],
),
],
)
class MyShellRouteData extends ShellRouteData {
const MyShellRouteData();
static final List<NavigatorObserver> $observers = <NavigatorObserver>[
MyNavigatorObserver()
];
@override
Widget builder(BuildContext context, GoRouterState state, Widget navigator) {
return MyShellRouteScreen(child: navigator);
}
}
class MyNavigatorObserver extends NavigatorObserver {
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {}
}
class MyShellRouteScreen extends StatelessWidget {
const MyShellRouteScreen({required this.child, super.key});
final Widget child;
int getCurrentIndex(BuildContext context) {
final String location = GoRouterState.of(context).uri.toString();
if (location.startsWith('/users')) {
return 1;
}
return 0;
}
@override
Widget build(BuildContext context) {
final int selectedIndex = getCurrentIndex(context);
return Scaffold(
body: Row(
children: <Widget>[
NavigationRail(
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.home),
label: Text('Home'),
),
NavigationRailDestination(
icon: Icon(Icons.group),
label: Text('Users'),
),
],
selectedIndex: selectedIndex,
onDestinationSelected: (int index) {
switch (index) {
case 0:
const HomeRouteData().go(context);
case 1:
const UsersRouteData().go(context);
}
},
),
const VerticalDivider(thickness: 1, width: 1),
Expanded(child: child),
],
),
);
}
}
class HomeRouteData extends GoRouteData {
const HomeRouteData();
@override
Widget build(BuildContext context, GoRouterState state) {
return const Center(child: Text('The home page'));
}
}
class UsersRouteData extends GoRouteData {
const UsersRouteData();
@override
Widget build(BuildContext context, GoRouterState state) {
return ListView(
children: <Widget>[
for (int userID = 1; userID <= 3; userID++)
ListTile(
title: Text('User $userID'),
onTap: () => UserRouteData(id: userID).go(context),
),
],
);
}
}
class DialogPage extends Page<void> {
/// A page to display a dialog.
const DialogPage({required this.child, super.key});
/// The widget to be displayed which is usually a [Dialog] widget.
final Widget child;
@override
Route<void> createRoute(BuildContext context) {
return DialogRoute<void>(
context: context,
settings: this,
builder: (BuildContext context) => child,
);
}
}
class UserRouteData extends GoRouteData {
const UserRouteData({required this.id});
// Without this static key, the dialog will not cover the navigation rail.
final int id;
@override
Page<void> buildPage(BuildContext context, GoRouterState state) {
return DialogPage(
key: state.pageKey,
child: Center(
child: SizedBox(
width: 300,
height: 300,
child: Card(child: Center(child: Text('User $id'))),
),
),
);
}
}