-
-
Save by90/2813291a0e13fdecd897aa3a5239a793 to your computer and use it in GitHub Desktop.
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 'dart:async'; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/widgets.dart'; | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
// This widget is the root of your application. | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp.router( | |
routeInformationParser: MyRouteInformationParser(), | |
routerDelegate: MyRouterDelegate(), | |
); | |
} | |
} | |
class MyHomePage extends StatefulWidget { | |
@override | |
_MyHomePageState createState() => _MyHomePageState(); | |
} | |
class _MyHomePageState extends State<MyHomePage> { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text( | |
"Home" | |
), | |
), | |
body: Center( | |
child: Text( | |
"this is home page" | |
), | |
), | |
floatingActionButton: FloatingActionButton( | |
child: Icon( | |
Icons.add, | |
), | |
onPressed: () { | |
MyRouterDelegate.of(context).pushNamed("/first"); | |
}, | |
), | |
); | |
} | |
} | |
class MyRouteInformationParser extends RouteInformationParser<RouteSettings> { | |
@override | |
Future<RouteSettings> parseRouteInformation(RouteInformation routeInformation) { | |
print("name: ${routeInformation.location}"); | |
return SynchronousFuture(RouteSettings( | |
name: routeInformation.location | |
)); | |
} | |
} | |
class MyRouterDelegate extends RouterDelegate<RouteSettings> | |
with ChangeNotifier { | |
MyRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>(); | |
final _pages = <MyPage>[]; | |
final GlobalKey<NavigatorState> navigatorKey; | |
static MyRouterDelegate of(BuildContext context) { | |
RouterDelegate routerDelegate = Router.of(context).routerDelegate; | |
assert(routerDelegate is MyRouterDelegate); | |
return routerDelegate as MyRouterDelegate; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Navigator( | |
key: navigatorKey, | |
pages: List.of(_pages), | |
onPopPage: (route, result) { | |
if (_pages.length > 1 && route.settings is MyPage) { | |
final MyPage<dynamic>? removed = _pages.lastWhere( | |
(element) => element.name == route.settings.name, | |
); | |
if (removed != null) { | |
_pages.remove(removed); | |
notifyListeners(); | |
} | |
} | |
return route.didPop(result); | |
}, | |
); | |
} | |
@override | |
Future<bool> popRoute() { | |
print("popRoute"); | |
final NavigatorState? navigator = navigatorKey.currentState; | |
if (navigator == null) | |
return SynchronousFuture<bool>(false); | |
return navigator.maybePop(); | |
} | |
@override | |
Future<void> setNewRoutePath(configuration) { | |
print("setNewRoutePath"); | |
_pages.add(getRoutePage( | |
name: configuration.name!, | |
arguments: configuration.arguments as Map<String, dynamic>?)); | |
return SynchronousFuture<void>(null); | |
} | |
Future<T?> pushNamed<T extends Object?>(String routeName, { | |
Map<String, dynamic>? arguments, | |
}) { | |
print("pushNamed: routeName: $routeName"); | |
MyPage<T?> page = getRoutePage(name: routeName, arguments: arguments); | |
_pages.add(page); | |
notifyListeners(); | |
return page.popped; | |
} | |
MyPage<T?> getRoutePage<T extends Object?>({ | |
required String name, | |
Map<String, dynamic>? arguments, | |
}) { | |
MyRouteSettings routeSettings = getRouteSettings(name: name, arguments: arguments); | |
MyPage<T?> page = MyPage( | |
key: UniqueKey(), | |
name: routeSettings.name ?? '', | |
widget: routeSettings.widget ?? Container(), | |
arguments: routeSettings.arguments); | |
return page; | |
} | |
} | |
class MyRouteSettings extends RouteSettings { | |
const MyRouteSettings({ | |
required String name, | |
Object? arguments, | |
this.widget, | |
this.showStatusBar, | |
this.routeName, | |
// this.pageRouteType, | |
// this.description, | |
// this.exts, | |
}) : super( | |
name: name, | |
arguments: arguments, | |
); | |
/// The Widget base on this route | |
final Widget? widget; | |
/// Whether show status bar. | |
final bool? showStatusBar; | |
/// The route name to track page | |
final String? routeName; | |
} | |
class MyPage<T> extends Page<T> { | |
MyPage({ | |
required String name, | |
required LocalKey key, | |
required this.widget, | |
Object? arguments, | |
// this.showStatusBar, | |
// this.routeName, | |
// this.pageRouteType, | |
// this.description, | |
// this.exts, | |
}) : super( | |
key: key, | |
name: name, | |
arguments: arguments, | |
); | |
final Widget widget; | |
Future<T> get popped => _popCompleter.future; | |
final Completer<T> _popCompleter = Completer<T>(); | |
bool get isCompleted => _popCompleter.isCompleted; | |
@override | |
Route<T> createRoute(BuildContext context) { | |
final Route<T> route = MaterialPageRoute( | |
settings: this, | |
builder: (BuildContext context) => widget, | |
); | |
return route | |
..popped.then((T? value) { | |
if (!isCompleted) { | |
_popCompleter.complete(value); | |
} | |
}); | |
} | |
} | |
MyRouteSettings getRouteSettings ({ | |
required String name, | |
Map<String, dynamic>? arguments, | |
}) { | |
final Map<String, dynamic> safeArguments = | |
arguments ?? const <String, dynamic>{}; | |
switch (name) { | |
case '/': | |
return MyRouteSettings( | |
name: name, | |
arguments: arguments, | |
widget: MyHomePage(), | |
); | |
case '/first': | |
return MyRouteSettings( | |
name: name, | |
arguments: arguments, | |
widget: FirstPage(), | |
); | |
case '/second': | |
return MyRouteSettings( | |
name: name, | |
arguments: arguments, | |
widget: SecondPage(), | |
); | |
default: | |
return const MyRouteSettings(name: '404'); | |
} | |
} | |
class FirstPage extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text( | |
"First Page" | |
), | |
), | |
body: Center( | |
child: Text( | |
"this is the first page" | |
), | |
), | |
floatingActionButton: FloatingActionButton( | |
child: Icon( | |
Icons.arrow_circle_up, | |
), | |
onPressed: () { | |
}, | |
), | |
); | |
} | |
} | |
class SecondPage extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text( | |
"Second Page" | |
), | |
), | |
body: Center( | |
child: Text( | |
"this is the second page" | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment