fix: 修复划转页面卡片互换动画效果

- 重写 AnimatedSwitcher 实现,移除多余的 Container 包裹
- 直接在 _buildAccountCard 上设置 ValueKey
- 使用 SlideTransition + FadeTransition 组合
- 上方卡片从上滑入,下方卡片从下滑入
- 动画时长 300ms,easeInOut 曲线
- 动画效果更流畅自然,卡片互换位置清晰可见
This commit is contained in:
2026-03-30 11:52:35 +08:00
parent e3c5a0b24d
commit ed98db66cf
84 changed files with 32906 additions and 32855 deletions

View File

@@ -165,42 +165,46 @@ class _TransferPageState extends State<TransferPage> {
padding: AppSpacing.pagePadding,
child: Column(
children: [
// 第一个卡片(根据方向显示"从"或"到"
AnimatedSwitcher(
// 第一个卡片位置 - 带动画
TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: 1),
duration: const Duration(milliseconds: 300),
transitionBuilder: (child, animation) {
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: Tween<Offset>(
begin: Offset(0, _direction == 1 ? -0.1 : 0.1),
end: Offset.zero,
).animate(CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
)),
child: child,
),
builder: (context, value, child) {
return AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
switchInCurve: Curves.easeInOut,
switchOutCurve: Curves.easeInOut,
transitionBuilder: (widget, animation) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, -1),
end: Offset.zero,
).animate(animation),
child: FadeTransition(
opacity: animation,
child: widget,
),
);
},
child: _direction == 1
? _buildAccountCard(
key: const ValueKey('from-card'),
label: '',
accountName: _fromLabel,
balance: _fromBalance,
isDark: isDark,
colorScheme: colorScheme,
)
: _buildAccountCard(
key: const ValueKey('to-card-top'),
label: '',
accountName: _toLabel,
balance: _toBalance,
isDark: isDark,
colorScheme: colorScheme,
),
);
},
child: Container(
key: ValueKey('card1-$_direction'),
child: _direction == 1
? _buildAccountCard(
label: '',
accountName: _fromLabel,
balance: _fromBalance,
isDark: isDark,
colorScheme: colorScheme,
)
: _buildAccountCard(
label: '',
accountName: _toLabel,
balance: _toBalance,
isDark: isDark,
colorScheme: colorScheme,
),
),
),
// 方向切换按钮(固定在中间)
@@ -227,44 +231,44 @@ class _TransferPageState extends State<TransferPage> {
),
),
// 第二个卡片(根据方向显示"到"或"从"
// 第二个卡片位置 - 带动画
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder: (child, animation) {
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: Tween<Offset>(
begin: Offset(0, _direction == 1 ? 0.1 : -0.1),
end: Offset.zero,
).animate(CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
)),
child: child,
switchInCurve: Curves.easeInOut,
switchOutCurve: Curves.easeInOut,
transitionBuilder: (widget, animation) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 1),
end: Offset.zero,
).animate(animation),
child: FadeTransition(
opacity: animation,
child: widget,
),
);
},
child: Container(
key: ValueKey('card2-$_direction'),
child: _direction == 1
? _buildAccountCard(
label: '',
accountName: _toLabel,
balance: _toBalance,
isDark: isDark,
colorScheme: colorScheme,
)
: _buildAccountCard(
label: '',
accountName: _fromLabel,
balance: _fromBalance,
isDark: isDark,
colorScheme: colorScheme,
),
),
child: _direction == 1
? _buildAccountCard(
key: const ValueKey('to-card'),
label: '',
accountName: _toLabel,
balance: _toBalance,
isDark: isDark,
colorScheme: colorScheme,
)
: _buildAccountCard(
key: const ValueKey('from-card-bottom'),
label: '',
accountName: _fromLabel,
balance: _fromBalance,
isDark: isDark,
colorScheme: colorScheme,
),
),
SizedBox(height: AppSpacing.lg),
// 金额输入卡片
_buildAmountSection(colorScheme, isDark),
@@ -297,6 +301,7 @@ class _TransferPageState extends State<TransferPage> {
/// 账户卡片
Widget _buildAccountCard({
Key? key,
required String label,
required String accountName,
required String balance,
@@ -304,6 +309,7 @@ class _TransferPageState extends State<TransferPage> {
required ColorScheme colorScheme,
}) {
return Container(
key: key,
width: double.infinity,
padding: EdgeInsets.all(AppSpacing.md),
decoration: BoxDecoration(