123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475 |
- import 'package:flutter/cupertino.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
- import 'package:lszlgl/base/base_state.dart';
- import 'package:lszlgl/page/unknow_page.dart';
- /// 路由监听
- class NavigatorPageObserver extends NavigatorObserver {
- static final NavigatorPageObserver instance = NavigatorPageObserver._();
- NavigatorPageObserver._();
- /// 路由信息
- /// 外部可以调用[MyNavigator.routeInfo]取值
- final RouteModel routeInfo = RouteModel();
- @override
- void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
- // 路由入栈
- routeInfo.update(showRoute: route, hideRoute: previousRoute);
- debugPrint('路由入栈 didPush:$routeInfo');
- _pageRecord();
- }
- @override
- void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
- // 路由出栈
- routeInfo.update(showRoute: previousRoute, hideRoute: route);
- debugPrint('路由出栈 didPop:$routeInfo');
- _pageRecord();
- }
- @override
- void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
- /*
- routeInfo.update(showRoute: previousRoute, hideRoute: route);
- // 路由移除
- debugPrint('路由移除 didRemove:$routeInfo');
- */
- }
- @override
- void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
- // 路由替换
- routeInfo.update(showRoute: newRoute, hideRoute: oldRoute);
- debugPrint('路由替换 didReplace:$routeInfo');
- _pageRecord();
- }
- @override
- void didStartUserGesture(Route<dynamic> route, Route<dynamic>? previousRoute) {
- // 手势控制路由
- }
- @override
- void didStopUserGesture() {
- // 手势控制路由结束
- }
- /// 页面统计
- void _pageRecord() {
- if (routeInfo.hideName != null) {
- // 页面关闭
- }
- if (routeInfo.showName != null) {
- // 页面显示
- }
- }
- }
- class RouteModel {
- /// 显示的路由
- Route<dynamic>? showRoute;
- /// 隐藏的路由
- Route<dynamic>? hideRoute;
- /// 前一个 widget 是否是一个页面(最好统一使用自定义路由)
- bool get isPage => hideRoute is PageRoute;
- /// 前一个 widget 是否是弹框
- bool get isDialog => !isPage;
- RouteModel();
- void update({Route<dynamic>? showRoute, Route<dynamic>? hideRoute}) {
- if (showRoute != null) this.showRoute = showRoute;
- if (hideRoute != null) this.hideRoute = hideRoute;
- }
- /// 显示路由的名称
- String? get showName => showRoute?.settings.name;
- /// 显示路由的配置信息
- Object? get showPageSetting => showRoute?.settings.arguments;
- /// 显示路由的业务参数
- Object? get showArguments {
- Object? args = showRoute?.settings.arguments;
- if (args != null) {
- if (args is PageSetting) {
- // PageSetting的参数
- return args.arguments;
- } else {
- // 原参数
- return args;
- }
- }
- return null;
- }
- /// 隐藏/移除路由的名称
- String? get hideName => hideRoute?.settings.name;
- /// 隐藏/移除路由的配置信息
- Object? get hidePageSetting => hideRoute?.settings.arguments;
- /// 隐藏/移除路由的业务参数
- Object? get hideArguments {
- Object? args = hideRoute?.settings.arguments;
- if (args != null) {
- if (args is PageSetting) {
- // PageSetting的参数
- return args.arguments;
- } else {
- // 原参数
- return args;
- }
- }
- return null;
- }
- @override
- String toString() {
- StringBuffer sb = StringBuffer();
- if (showRoute != null) {
- sb.write('showName:$showName showArgs:$showArguments ');
- }
- if (hideRoute != null) {
- sb.write('hideName:$hideName hideArgs:$hideArguments');
- }
- return sb.toString();
- }
- }
- /// 路由页面Builder函数
- typedef MyNavigatorBuilder = Widget Function(BuildContext context, Object? arguments);
- class MyNavigator {
- MyNavigator._();
- /// 全局Navigator
- static final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
- /// 全局路由监听
- static final NavigatorPageObserver navigatorObs = NavigatorPageObserver.instance;
- /// 最新路由信息
- static RouteModel routeInfo = navigatorObs.routeInfo;
- /// Widget路由监听
- static final RouteObserver<ModalRoute<void>> routeObs = RouteObserver<ModalRoute<void>>();
- /// 自定义路由拦截
- static Route<dynamic> generateRoute(RouteSettings settings) {
- var routeName = settings.name;
- // 是否dialog
- bool fullscreenDialog = false;
- // 是否可截屏
- bool allowSnapshotting = true;
- // 业务传参
- Object? args;
- // 页面路由样式
- RouteType routeType = RouteType.cupertino;
- // 获取路由配置
- if (settings.arguments != null && settings.arguments is PageSetting) {
- PageSetting pageSetting = settings.arguments as PageSetting;
- fullscreenDialog = pageSetting.fullscreenDialog ?? false;
- allowSnapshotting = pageSetting.allowSnapshotting ?? true;
- routeType = pageSetting.routeType ?? RouteType.cupertino;
- args = pageSetting.arguments;
- } else {
- args = settings.arguments;
- }
- // 创建路由
- MyNavigatorBuilder? builder = rRouteMap[routeName];
- builder ??= (context, args) => UnknownPage(name: settings.name);
- switch (routeType) {
- case RouteType.material:
- return MaterialPageRoute(
- builder: (context) => builder!.call(context, args),
- settings: settings,
- fullscreenDialog: fullscreenDialog,
- allowSnapshotting: allowSnapshotting,
- );
- case RouteType.normal:
- return PageRouteBuilder(
- pageBuilder: (context, animation, secondaryAnimation) => builder!.call(context, args),
- settings: settings,
- fullscreenDialog: fullscreenDialog,
- allowSnapshotting: allowSnapshotting,
- );
- case RouteType.cupertino:
- default:
- return CupertinoPageRoute(
- builder: (context) => builder!.call(context, args),
- settings: settings,
- fullscreenDialog: fullscreenDialog,
- allowSnapshotting: allowSnapshotting,
- );
- }
- }
- /// 添加新页面
- static Future<T?> push<T extends Object?>(
- String name, {
- Object? args,
- bool fullscreenDialog = false,
- bool allowSnapshotting = true,
- RouteType routeType = RouteType.cupertino,
- }) {
- PageSetting setting = PageSetting(
- arguments: args,
- fullscreenDialog: fullscreenDialog,
- allowSnapshotting: allowSnapshotting,
- routeType: routeType,
- );
- return navigator.currentState!.pushNamed(name, arguments: setting);
- }
- /// 添加新页面 并 替换当前页面
- static Future<T?> pushReplace<T extends Object?, TO extends Object?>(
- String name, {
- TO? result,
- Object? args,
- bool fullscreenDialog = false,
- bool allowSnapshotting = true,
- RouteType routeType = RouteType.cupertino,
- }) {
- PageSetting setting = PageSetting(
- arguments: args,
- fullscreenDialog: fullscreenDialog,
- allowSnapshotting: allowSnapshotting,
- routeType: routeType,
- );
- return navigator.currentState!.pushReplacementNamed(name, result: result, arguments: setting);
- }
- /// 添加新页面 并 移除一些页面,直至predicate返回true
- static Future<T?> pushRemoveUntil<T extends Object?>(
- String name,
- RoutePredicate predicate, {
- Object? args,
- bool fullscreenDialog = false,
- bool allowSnapshotting = true,
- RouteType routeType = RouteType.cupertino,
- }) {
- PageSetting setting = PageSetting(
- arguments: args,
- fullscreenDialog: fullscreenDialog,
- allowSnapshotting: allowSnapshotting,
- routeType: routeType,
- );
- return navigator.currentState!.pushNamedAndRemoveUntil(name, predicate, arguments: setting);
- }
- /// 移除路由栈顶页面
- static void pop<T extends Object?>([T? result]) {
- return navigator.currentState!.pop(result);
- }
- /// 移除路由栈顶页面 并 添加新页面
- static Future<T?> popAndPush<T extends Object?, TO extends Object?>(
- String name, {
- TO? result,
- Object? args,
- bool fullscreenDialog = false,
- bool allowSnapshotting = true,
- RouteType routeType = RouteType.cupertino,
- }) {
- PageSetting setting = PageSetting(
- arguments: args,
- fullscreenDialog: fullscreenDialog,
- allowSnapshotting: allowSnapshotting,
- routeType: routeType,
- );
- return navigator.currentState!.popAndPushNamed(name, result: result, arguments: setting);
- }
- /// 移除一些页面, 直至predicate返回true
- static void popUntil(RoutePredicate predicate) {
- return navigator.currentState!.popUntil(predicate);
- }
- /// 显示Dialog
- static Future<T?> showDialog<T>({
- required WidgetBuilder builder,
- SmartDialogController? controller,
- Alignment? alignment,
- bool? clickDismiss,
- bool? usePenetrate,
- Color? maskColor,
- Widget? maskWidget,
- VoidCallback? onDismiss,
- VoidCallback? onMask,
- Duration? displayTime,
- String? tag,
- bool? keepSingle,
- bool? permanent,
- bool? useSystem,
- bool? bindPage,
- BuildContext? bindWidget,
- Rect? ignoreArea,
- }) {
- return SmartDialog.show(
- builder: builder,
- controller: controller,
- alignment: alignment,
- clickMaskDismiss: clickDismiss,
- usePenetrate: usePenetrate,
- useAnimation: null,
- animationType: null,
- nonAnimationTypes: null,
- animationBuilder: null,
- animationTime: null,
- maskColor: maskColor,
- maskWidget: maskWidget,
- onDismiss: onDismiss,
- onMask: onMask,
- displayTime: displayTime,
- tag: tag,
- backDismiss: clickDismiss,
- keepSingle: keepSingle,
- permanent: permanent,
- useSystem: useSystem,
- bindPage: bindPage,
- bindWidget: bindWidget,
- ignoreArea: ignoreArea,
- );
- }
- static Future<void> showToast(
- String msg, {
- SmartDialogController? controller,
- Duration? displayTime,
- Alignment? alignment,
- bool? clickMaskDismiss,
- Color? maskColor,
- Widget? maskWidget,
- VoidCallback? onDismiss,
- SmartToastType? displayType,
- }) =>
- SmartDialog.showToast(
- msg,
- controller: controller,
- displayTime: displayTime,
- alignment: alignment ?? Alignment.center,
- clickMaskDismiss: clickMaskDismiss,
- animationType: null,
- nonAnimationTypes: null,
- animationBuilder: null,
- usePenetrate: null,
- useAnimation: null,
- animationTime: null,
- maskColor: maskColor,
- maskWidget: maskWidget,
- onDismiss: onDismiss,
- onMask: null,
- consumeEvent: null,
- debounce: null,
- displayType: displayType,
- builder: null,
- );
- static Future<T?> showLoading<T>({
- String msg = '加载中',
- bool? clickDismiss,
- SmartDialogController? controller,
- Alignment? alignment,
- bool? usePenetrate,
- Color? maskColor,
- Widget? maskWidget,
- VoidCallback? onDismiss,
- VoidCallback? onMask,
- Duration? displayTime,
- }) {
- return SmartDialog.showLoading(
- msg: msg,
- controller: controller,
- alignment: alignment,
- clickMaskDismiss: clickDismiss,
- animationType: null,
- nonAnimationTypes: null,
- animationBuilder: null,
- usePenetrate: usePenetrate,
- useAnimation: null,
- animationTime: null,
- maskColor: maskColor,
- maskWidget: maskWidget,
- onDismiss: onDismiss,
- onMask: onMask,
- displayTime: displayTime,
- backDismiss: clickDismiss,
- builder: null,
- );
- }
- static Future<void> dismiss<T>({
- SmartStatus status = SmartStatus.smart,
- String? tag,
- T? result,
- bool force = false,
- }) =>
- SmartDialog.dismiss(
- status: status,
- tag: tag,
- result: result,
- force: force,
- );
- static Future<void> dismissLoading<T>({
- String? tag,
- T? result,
- bool force = false,
- }) =>
- SmartDialog.dismiss(
- status: SmartStatus.loading,
- tag: tag,
- result: result,
- force: force,
- );
- }
- /// 页面设置信息
- class PageSetting {
- /// 全屏Dialog
- final bool? fullscreenDialog;
- /// 是否可截屏
- final bool? allowSnapshotting;
- /// 页面类型
- final RouteType? routeType;
- /// 业务参数
- final Object? arguments;
- PageSetting({
- this.fullscreenDialog,
- this.allowSnapshotting,
- this.routeType = RouteType.cupertino,
- this.arguments,
- });
- @override
- String toString() => {
- 'fullscreenDialog': fullscreenDialog,
- 'allowSnapshotting': allowSnapshotting,
- 'routeType': routeType,
- 'arguments': arguments,
- }.toString();
- }
- enum RouteType {
- /// iOS样式路由
- cupertino,
- /// Android样式路由
- material,
- /// 普通路由(无动画效果)
- normal,
- }
|