Created
October 9, 2020 16:05
-
-
Save magicleon94/250a0a4f236cf5b0704be80687fa7e30 to your computer and use it in GitHub Desktop.
Flutter Navigator 2.0 + Notification test
This file contains 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'; | |
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