hi-client/lib/app/routes/transitions/slide_transparent_transition.dart
2025-12-01 06:54:18 -08:00

240 lines
7.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<double> animation,
Animation<double> 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<Offset>(
begin: newPageBeginOffset,
end: Offset.zero,
).animate(CurvedAnimation(
parent: animation,
curve: animationCurve,
));
// 旧页面滑出动画:从中心滑出到屏幕外
final oldPageAnimation = Tween<Offset>(
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<double> animation,
Animation<double> 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<Offset>(
begin: newPageBeginOffset,
end: Offset.zero,
).animate(CurvedAnimation(
parent: animation,
curve: animationCurve,
));
// 旧页面滑出动画:从中心滑出到屏幕外
final oldPageAnimation = Tween<Offset>(
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<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
const double slideDistance = 1.0;
// 旧页面出场动画
final oldPageEndOffset = direction == SlideDirection.rightToLeft
? Offset(-slideDistance, 0)
: Offset(slideDistance, 0);
final oldPageAnimation = Tween<Offset>(
begin: Offset.zero,
end: oldPageEndOffset,
).animate(CurvedAnimation(
parent: secondaryAnimation,
curve: curve ?? Curves.easeOut,
));
// 新页面入场无动画
final newPageAnimation = Tween<Offset>(
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,
);
},
);
}
}