Skip to content

Instantly share code, notes, and snippets.

@magicleon94
Created October 9, 2020 16:05
Show Gist options
  • Save magicleon94/250a0a4f236cf5b0704be80687fa7e30 to your computer and use it in GitHub Desktop.
Save magicleon94/250a0a4f236cf5b0704be80687fa7e30 to your computer and use it in GitHub Desktop.
Flutter Navigator 2.0 + Notification test
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final delegate = AppRouteDelegate();
final parser = AppRouteInformationParser();
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: delegate,
routeInformationParser: parser,
title: 'Nav2',
);
}
}
class AppRoutePath {
final String message;
final bool isUnknown;
AppRoutePath.home()
: message = null,
isUnknown = false;
AppRoutePath.detail(this.message) : isUnknown = false;
AppRoutePath.unknown()
: message = null,
isUnknown = true;
}
class AppRoutingEvent extends Notification {
final String message;
AppRoutingEvent(this.message);
}
class AppRouteDelegate extends RouterDelegate<AppRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<AppRoutePath> {
final GlobalKey<NavigatorState> navigatorKey;
AppRouteDelegate() : navigatorKey = GlobalKey<NavigatorState>();
String message;
bool _handleNavigationEvent(AppRoutingEvent event) {
message = event.message;
notifyListeners();
return true;
}
AppRoutePath get currentConfiguration =>
message == null ? AppRoutePath.home() : AppRoutePath.detail(message);
@override
Widget build(BuildContext context) {
return NotificationListener<AppRoutingEvent>(
onNotification: _handleNavigationEvent,
child: Navigator(
key: navigatorKey,
pages: [
MaterialPage(
key: ValueKey('HomeScreen'),
child: HomeScreen(),
),
if (message != null)
MaterialPage(
key: ValueKey(message),
child: DetailScreen(
message: message,
),
)
],
onPopPage: (route, result) {
if (!route.didPop(result)) {
return false;
}
message = null;
notifyListeners();
return true;
},
),
);
}
@override
Future<void> setNewRoutePath(AppRoutePath path) async {
if (path.isUnknown) {
message = null;
}
if (path.message != null) {
message = path.message;
}
}
}
class AppRouteInformationParser extends RouteInformationParser<AppRoutePath> {
@override
Future<AppRoutePath> parseRouteInformation(
RouteInformation routeInformation) async {
final uri = Uri.parse(routeInformation.location);
if (uri.pathSegments.isEmpty) {
return AppRoutePath.home();
}
if (uri.pathSegments.length == 2) {
if (uri.pathSegments[0] != 'details') return AppRoutePath.unknown();
final message = uri.pathSegments[1];
return AppRoutePath.detail(message);
}
return AppRoutePath.unknown();
}
@override
RouteInformation restoreRouteInformation(AppRoutePath path) {
if (path.message == null) {
return RouteInformation(location: '/');
}
if (path.message != null) {
return RouteInformation(location: '/details/${path.message}');
}
return null;
}
}
class DetailScreen extends StatelessWidget {
final String message;
const DetailScreen({Key key, this.message}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Detail')),
body: Center(
child: Text(message ?? 'No message'),
),
);
}
}
class HomeScreen extends StatefulWidget {
final Function(String) onTap;
const HomeScreen({Key key, this.onTap}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
void onTap(String message) {
widget.onTap?.call(message) ?? AppRoutingEvent(message).dispatch(context);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home')),
body: Column(
children: [
TextButton(
onPressed: () => onTap('Detail 1'),
child: Text('Detail 1'),
),
TextButton(
onPressed: () => onTap('Detail 2'),
child: Text('Detail 2'),
)
],
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment