import 'package:flutter/material.dart'; import 'package:get/get.dart'; enum SlideDirection { leftToRight, rightToLeft } /// 智能转场类,根据路由上下文决定转场方向 class ContextAwareSlideTransition extends CustomTransition { final String targetRoute; final Duration duration; ContextAwareSlideTransition({ required this.targetRoute, this.duration = const Duration(milliseconds: 350), }); @override Widget buildTransition( BuildContext context, Curve? curve, Alignment? alignment, Animation animation, Animation secondaryAnimation, Widget child) { // 获取当前路由信息 final currentRoute = Get.currentRoute; final previousRoute = Get.previousRoute; // 决定转场方向 SlideDirection direction = _determineDirection(currentRoute, previousRoute); // 确保移动距离一致:都是1.0个屏幕宽度 const double slideDistance = 1.0; // 新页面入场方向 final newPageBeginOffset = direction == SlideDirection.rightToLeft ? Offset(slideDistance, 0) : Offset(-slideDistance, 0); // 旧页面滑出方向(与新页面相反,距离相同) final oldPageEndOffset = direction == SlideDirection.rightToLeft ? Offset(-slideDistance, 0) : Offset(slideDistance, 0); // 使用相同的动画曲线确保同步 final animationCurve = curve ?? Curves.elasticOut; // 新页面滑入动画:从屏幕外滑入到中心 final newPageAnimation = Tween( begin: newPageBeginOffset, end: Offset.zero, ).animate(CurvedAnimation( parent: animation, curve: animationCurve, )); // 旧页面滑出动画:从中心滑出到屏幕外 final oldPageAnimation = Tween( begin: Offset.zero, end: oldPageEndOffset, ).animate(CurvedAnimation( parent: secondaryAnimation, curve: animationCurve, )); // 使用 AnimatedBuilder 来监听 secondaryAnimation 的变化 return AnimatedBuilder( animation: secondaryAnimation, builder: (context, _) { // 如果 secondaryAnimation 正在运行,说明这是旧页面 if (secondaryAnimation.status == AnimationStatus.forward || secondaryAnimation.status == AnimationStatus.reverse) { return SlideTransition( position: oldPageAnimation, child: child, ); } // 否则这是新页面 return SlideTransition( position: newPageAnimation, child: child, ); }, ); } /// 根据路由上下文决定转场方向 SlideDirection _determineDirection(String currentRoute, String previousRoute) { // 如果目标路由是 HI_MENU if (targetRoute == '/hi_menu') { // 从 home 页面来的,使用左到右(menu 从左侧进入) if (previousRoute == '/kr_home' || previousRoute.contains('kr_home')) { return SlideDirection.leftToRight; } // 去其他页面,使用右到左 else { return SlideDirection.rightToLeft; } } // 默认使用右到左 return SlideDirection.rightToLeft; } } class SlideTransparentTransition extends CustomTransition { final SlideDirection direction; final Duration duration; SlideTransparentTransition({ this.direction = SlideDirection.rightToLeft, this.duration = const Duration(milliseconds: 1000), }); @override Widget buildTransition( BuildContext context, Curve? curve, Alignment? alignment, Animation animation, Animation secondaryAnimation, Widget child) { // 确保移动距离一致:都是1.0个屏幕宽度 const double slideDistance = 1.0; // 新页面入场方向 final newPageBeginOffset = direction == SlideDirection.rightToLeft ? Offset(slideDistance, 0) : Offset(-slideDistance, 0); // 旧页面滑出方向(与新页面相反,距离相同) final oldPageEndOffset = direction == SlideDirection.rightToLeft ? Offset(-slideDistance, 0) : Offset(slideDistance, 0); // 使用相同的动画曲线确保同步 final animationCurve = curve ?? Curves.elasticOut; // 新页面滑入动画:从屏幕外滑入到中心 final newPageAnimation = Tween( begin: newPageBeginOffset, end: Offset.zero, ).animate(CurvedAnimation( parent: animation, curve: animationCurve, )); // 旧页面滑出动画:从中心滑出到屏幕外 final oldPageAnimation = Tween( begin: Offset.zero, end: oldPageEndOffset, ).animate(CurvedAnimation( parent: secondaryAnimation, curve: animationCurve, )); // 使用 AnimatedBuilder 来监听 secondaryAnimation 的变化 return AnimatedBuilder( animation: secondaryAnimation, builder: (context, _) { // 如果 secondaryAnimation 正在运行,说明这是旧页面 if (secondaryAnimation.status == AnimationStatus.forward || secondaryAnimation.status == AnimationStatus.reverse) { return SlideTransition( position: oldPageAnimation, child: child, ); } // 否则这是新页面 return SlideTransition( position: newPageAnimation, child: child, ); }, ); } } class SlideOutOnlyTransition extends CustomTransition { final SlideDirection direction; final Duration duration; SlideOutOnlyTransition({ this.direction = SlideDirection.rightToLeft, this.duration = const Duration(milliseconds: 350), }); @override Widget buildTransition( BuildContext context, Curve? curve, Alignment? alignment, Animation animation, Animation secondaryAnimation, Widget child) { const double slideDistance = 1.0; // 旧页面出场动画 final oldPageEndOffset = direction == SlideDirection.rightToLeft ? Offset(-slideDistance, 0) : Offset(slideDistance, 0); final oldPageAnimation = Tween( begin: Offset.zero, end: oldPageEndOffset, ).animate(CurvedAnimation( parent: secondaryAnimation, curve: curve ?? Curves.easeOut, )); // 新页面入场无动画 final newPageAnimation = Tween( begin: Offset.zero, end: Offset.zero, ).animate(animation); return AnimatedBuilder( animation: secondaryAnimation, builder: (context, _) { // secondaryAnimation 正在执行,表示旧页面在出场 if (secondaryAnimation.status == AnimationStatus.forward || secondaryAnimation.status == AnimationStatus.reverse) { return SlideTransition( position: oldPageAnimation, child: child, ); } // 否则新页面直接显示,无动画 return SlideTransition( position: newPageAnimation, child: child, ); }, ); } }