feat: 为划转页面账户卡片添加位置互换动画
- 移除按钮旋转动画,保持按钮静止 - 两个账户卡片(从/到)平滑互换位置 - 使用 AnimatedSwitcher + FadeTransition + SlideTransition - 动画时长 300ms,easeOut 曲线 - 上方卡片向上滑出,下方卡片向下滑入 - 视觉效果更流畅自然
This commit is contained in:
@@ -18,29 +18,14 @@ class TransferPage extends StatefulWidget {
|
||||
State<TransferPage> createState() => _TransferPageState();
|
||||
}
|
||||
|
||||
class _TransferPageState extends State<TransferPage> with SingleTickerProviderStateMixin {
|
||||
class _TransferPageState extends State<TransferPage> {
|
||||
final _amountController = TextEditingController();
|
||||
int _direction = 1; // 1: 资金→交易, 2: 交易→资金
|
||||
bool _isLoading = false;
|
||||
late AnimationController _rotationController;
|
||||
late Animation<double> _rotationAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 初始化旋转动画
|
||||
_rotationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
vsync: this,
|
||||
);
|
||||
_rotationAnimation = Tween<double>(
|
||||
begin: 0,
|
||||
end: 0.5, // 180度 = 0.5 圈
|
||||
).animate(CurvedAnimation(
|
||||
parent: _rotationController,
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<AssetProvider>().refreshAll(force: true);
|
||||
});
|
||||
@@ -49,7 +34,6 @@ class _TransferPageState extends State<TransferPage> with SingleTickerProviderSt
|
||||
@override
|
||||
void dispose() {
|
||||
_amountController.dispose();
|
||||
_rotationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -144,17 +128,11 @@ class _TransferPageState extends State<TransferPage> with SingleTickerProviderSt
|
||||
_amountController.text = amount.toStringAsFixed(8).replaceAll(RegExp(r'\.?0+$'), '');
|
||||
}
|
||||
|
||||
/// 切换方向并触发旋转动画
|
||||
/// 切换方向
|
||||
void _toggleDirection() {
|
||||
setState(() {
|
||||
_direction = _direction == 1 ? 2 : 1;
|
||||
});
|
||||
|
||||
// 触发旋转动画
|
||||
if (_rotationController.status == AnimationStatus.completed) {
|
||||
_rotationController.reset();
|
||||
}
|
||||
_rotationController.forward();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -187,53 +165,106 @@ class _TransferPageState extends State<TransferPage> with SingleTickerProviderSt
|
||||
padding: AppSpacing.pagePadding,
|
||||
child: Column(
|
||||
children: [
|
||||
// 从账户卡片
|
||||
_buildAccountCard(
|
||||
label: '从',
|
||||
accountName: _fromLabel,
|
||||
balance: _fromBalance,
|
||||
isDark: isDark,
|
||||
colorScheme: colorScheme,
|
||||
// 第一个卡片(根据方向显示"从"或"到")
|
||||
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,
|
||||
),
|
||||
);
|
||||
},
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// 方向切换按钮
|
||||
// 方向切换按钮(固定在中间)
|
||||
GestureDetector(
|
||||
onTap: _toggleDirection,
|
||||
child: RotationTransition(
|
||||
turns: _rotationAnimation,
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(vertical: AppSpacing.sm),
|
||||
padding: EdgeInsets.all(AppSpacing.sm + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.primary,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: colorScheme.primary.withOpacity(0.3),
|
||||
blurRadius: 8,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Icon(
|
||||
Icons.swap_vert,
|
||||
color: colorScheme.onPrimary,
|
||||
size: 22,
|
||||
),
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(vertical: AppSpacing.sm),
|
||||
padding: EdgeInsets.all(AppSpacing.sm + AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.primary,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: colorScheme.primary.withOpacity(0.3),
|
||||
blurRadius: 8,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Icon(
|
||||
Icons.swap_vert,
|
||||
color: colorScheme.onPrimary,
|
||||
size: 22,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// 到账户卡片
|
||||
_buildAccountCard(
|
||||
label: '到',
|
||||
accountName: _toLabel,
|
||||
balance: _toBalance,
|
||||
isDark: isDark,
|
||||
colorScheme: colorScheme,
|
||||
// 第二个卡片(根据方向显示"到"或"从")
|
||||
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,
|
||||
),
|
||||
);
|
||||
},
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
|
||||
// 金额输入卡片
|
||||
_buildAmountSection(colorScheme, isDark),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user