/* * * 路由封装 * @params* [context] 当前页面上下文 * @params* [targetPage] 跳转页面 非命名参数跳转时是 BuildContext 类型,路由命名参数跳转时是 字符串类型 * @params [isPushNamed] 是否是命名参数跳转 默认false 非命名参数跳转; true 是 * @params [arguments] 携带的参数 默认null * @params [opaque] 是否背景透明 默认false 不透明; true为透明 * @params [isReplace] 是否替换当前页面 A-B 默认0 不替换; // 0 不替换 1 替换当前 2 替换当前及之前所有 * @params [cb] // 返回上一级的回调函数 value 为传给上一级的参数 * * * * 用法: * // 页面跳转 GotoPage.pushPage( context: context, // targetPage: AppRoutes.mePage, targetPage: MePage(), animationType: AnimationType.rightToLeft, arguments: {"name": "gaolong"}, cb: (value) => {print("---mePage返回的数据---$value------")}, ); * * * */ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'device_utils.dart'; //页面跳转动画的方式 enum AnimationType { rightToLeft, leftToRight, bottomToTop, topToBottom } class GotoPage { // 非命名方式跳转 直接初始化页面对象 static void _switchPageNotNamed({ required BuildContext context, required dynamic targetPage, AnimationType? animationType = AnimationType.rightToLeft, int startMills = 300, // 动画过渡时间 300ms Object? arguments, num isReplace = 0, // 0 不替换 1 替换当前 2 替换当前及之前所有 void Function(dynamic value)? cb, }) { PageRoute pageRoute; if (DeviceUtils.isAndroid) { // 安卓 pageRoute = PageRouteBuilder( settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments), transitionDuration: Duration(milliseconds: startMills), transitionsBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation, Widget child) { return SlideTransition( position: _createSlideTween(animationType).animate(animation), child: child, ); }, pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) { return targetPage; }, ); } else if (DeviceUtils.isIOS) { // 苹果 pageRoute = CupertinoPageRoute( builder: (BuildContext context) { return targetPage; }, settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments), ); } else { // 其他 pageRoute = MaterialPageRoute( builder: (BuildContext context) { return targetPage; }, settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments), ); } if (isReplace == 0) { // 不替换 Navigator.of(context).push(pageRoute).then((value) { if (cb != null) { cb(value); } }); } else if (isReplace == 1) { // 替换当前 Navigator.of(context).pushReplacement(pageRoute).then((value) { if (cb != null) { cb(value); } }); } else { // 替换当前及之前所有 Navigator.of(context).pushAndRemoveUntil(pageRoute, (Route? route) => route == null).then((value) { if (cb != null) { cb(value); } }); } } // 命名路由方式跳转 static void _switchPageByNamed({ required BuildContext context, required String targetPage, AnimationType? animationType = AnimationType.rightToLeft, int startMills = 300, // 动画过渡时间 300ms Object? arguments, num isReplace = 0, // 0 不替换 1 替换当前 2 替换当前及之前所有 void Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数 }) { if (isReplace == 0) { // 不替换 Navigator.of(context).pushNamed(targetPage, arguments: arguments).then((value) => { if (cb != null) {cb(value)} }); } else if (isReplace == 1) { // 替换当前 Navigator.of(context).pushReplacementNamed(targetPage, arguments: arguments).then((value) => { if (cb != null) {cb(value)} }); } else { // 替换当前及以前所有 Navigator.of(context) .pushNamedAndRemoveUntil(targetPage, (Route route) => false, arguments: arguments) .then((value) => { if (cb != null) {cb(value)} }); } } /// 1、普通跳转 static void pushPage({ required BuildContext context, required dynamic targetPage, // 非命名跳转时类型是 PageRoute 命令跳转时是 String AnimationType? animationType = AnimationType.rightToLeft, int startMills = 300, // 动画过渡时间 300ms Object? arguments, //携带参数 num isReplace = 0, // 0 不替换 1 替换当前 2 替换当前及之前所有 void Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数 }) { bool _isPushNamed = targetPage is String ? true : false; if (!_isPushNamed) { //非路由命名方式跳转 _switchPageNotNamed( context: context, targetPage: targetPage, animationType: animationType, startMills: startMills, arguments: arguments, isReplace: isReplace, cb: cb, ); } else { // 路由命名跳转 _switchPageByNamed( context: context, targetPage: targetPage, animationType: animationType, startMills: startMills, arguments: arguments, isReplace: isReplace, cb: cb, ); } } /// 2、滑动过渡跳转 static void pushPageBySlide({ required BuildContext context, required dynamic targetPage, // 非命名跳转时类型是 PageRoute 命令跳转时是 String //默认'rightToLeft', 'leftToRight' 'bottomToTop' 'topToBottom' AnimationType? animationType = AnimationType.rightToLeft, bool? isPushNamed = true, // 是否是路由命名跳转 true 是 false 否 bool opaque = true, // 背景透明方式 true: 不透明 false: 透明 Object? arguments, int startMills = 300, num isReplace = 0, // 0 不替换 1 替换当前 2 替换当前及之前所有 void Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数 }) { bool _isPushNamed = targetPage is String ? true : false; if (_isPushNamed) { // 命名跳转 命名跳转时 没有动画效果 默认页面从 右向左切换 _switchPageByNamed( context: context, targetPage: targetPage, arguments: arguments, isReplace: isReplace, cb: cb); } else { // 非命名跳转 PageRoute pageRoute = PageRouteBuilder( settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments), ///背景透明方式 true: 不透明 false: 透明 opaque: opaque, pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) { return targetPage; }, transitionDuration: Duration(milliseconds: startMills), ///动画 transitionsBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation, Widget child) { return SlideTransition( position: _createSlideTween(animationType).animate(animation), child: child, ); }, ); if (isReplace == 0) { /// 不替换 Navigator.of(context).push(pageRoute).then((value) { if (cb != null) { cb(value); } }); } else if (isReplace == 1) { /// 替换当前 Navigator.of(context).pushReplacement(pageRoute).then((value) { if (cb != null) { cb(value); } }); } else { /// 替换当前及之前所有 Navigator.of(context).pushAndRemoveUntil(pageRoute, (Route? route) => route == null).then((value) { if (cb != null) { cb(value); } }); } } } static _createSlideTween(animationType) { Offset currentOffset; switch (animationType) { case AnimationType.rightToLeft: currentOffset = Offset(1, 0); break; case AnimationType.leftToRight: currentOffset = Offset(-1, 0); break; case AnimationType.bottomToTop: currentOffset = Offset(0, 1); break; case AnimationType.topToBottom: currentOffset = Offset(0, -1); break; default: currentOffset = Offset(1, 0); } return Tween( begin: currentOffset, end: Offset.zero, ); } /// 3、带渐变动画跳转 static void pushPageByFade({ required BuildContext context, required Widget targetPage, bool opaque = false, // 背景透明方式 true: 不透明 false: 透明 dynamic arguments, int startMills = 300, num isReplace = 0, // 0 不替换 1 替换当前 2 替换当前及之前所有 Function(dynamic value)? cb, // 返回上一级的回调函数 value 为传给上一级的参数 }) { PageRoute pageRoute = PageRouteBuilder( settings: RouteSettings(name: context.widget.key.toString(), arguments: arguments ?? null), ///背景透明方式 true: 不透明 false: 透明 opaque: opaque, pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) { return targetPage; }, transitionDuration: Duration(milliseconds: startMills), ///动画 transitionsBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation, Widget child) { return FadeTransition( opacity: animation, child: child, ); }, ); if (isReplace == 0) { /// 不替换 Navigator.of(context).push(pageRoute).then((value) { if (cb != null) { cb(value); } }); } else if (isReplace == 1) { /// 替换当前 Navigator.of(context).pushReplacement(pageRoute).then((value) { if (cb != null) { cb(value); } }); } else { /// 替换当前及之前所有 Navigator.of(context).pushAndRemoveUntil(pageRoute, (Route? route) => route == null).then((value) { if (cb != null) { cb(value); } }); } } static Route _createRoute(parentContext, Widget targetPage, int startMills, int reversMills, bool opaque, {dynamic arguments}) { return PageRouteBuilder( settings: RouteSettings(name: parentContext?.widget?.key ?? '', arguments: arguments ?? null), opaque: opaque, // 背景透明方式 true: 不透明 false: 透明 pageBuilder: (context, animation, secondaryAnimation) { return targetPage; }, transitionDuration: Duration(milliseconds: startMills), reverseTransitionDuration: Duration(milliseconds: reversMills), transitionsBuilder: (context, animation, secondaryAnimation, child) { var rectAnimation = _createTween(parentContext).chain(CurveTween(curve: Curves.ease)).animate(animation); return Stack( children: [ PositionedTransition(rect: rectAnimation, child: child), ], ); }, ); } static Tween _createTween(BuildContext context) { var windowSize = MediaQuery.of(context).size; var box = context.findRenderObject() as RenderBox; var rect = box.localToGlobal(Offset.zero) & box.size; var relativeRect = RelativeRect.fromSize(rect, windowSize); return RelativeRectTween( begin: relativeRect, end: RelativeRect.fill, ); } }