feat(theme): update color scheme with new Slate theme and improved surface hierarchy
Updated the app's color scheme to implement a new "Slate" theme with refined dark and light variants. Changed background colors from #0A0E14 to #0B1120 for dark mode and updated surface layer colors to follow Material Design 3 specifications. Modified text colors and outline variants for better contrast and accessibility. Updated font sizes in transaction details screen from 11px to 12px for improved readability.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import '../../../core/theme/app_color_scheme.dart';
|
||||
import '../../../core/theme/app_spacing.dart';
|
||||
import '../../../providers/asset_provider.dart';
|
||||
import '../../../data/models/account_models.dart';
|
||||
import '../../shared/ui_constants.dart';
|
||||
import '../../components/neon_glow.dart';
|
||||
|
||||
/// 划转页面 - 币安风格
|
||||
/// 划转页面
|
||||
class TransferPage extends StatefulWidget {
|
||||
const TransferPage({super.key});
|
||||
|
||||
@@ -20,6 +18,7 @@ class TransferPage extends StatefulWidget {
|
||||
|
||||
class _TransferPageState extends State<TransferPage> {
|
||||
final _amountController = TextEditingController();
|
||||
final _focusNode = FocusNode();
|
||||
int _direction = 1; // 1: 资金→交易, 2: 交易→资金
|
||||
bool _isLoading = false;
|
||||
|
||||
@@ -34,6 +33,7 @@ class _TransferPageState extends State<TransferPage> {
|
||||
@override
|
||||
void dispose() {
|
||||
_amountController.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -124,7 +124,6 @@ class _TransferPageState extends State<TransferPage> {
|
||||
void _setQuickAmount(double percent) {
|
||||
final available = double.tryParse(_availableBalance) ?? 0;
|
||||
final amount = available * percent;
|
||||
// 保留8位小数,去除末尾0
|
||||
_amountController.text = amount.toStringAsFixed(8).replaceAll(RegExp(r'\.?0+$'), '');
|
||||
}
|
||||
|
||||
@@ -140,21 +139,36 @@ class _TransferPageState extends State<TransferPage> {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
// Theme-aware colors matching .pen design tokens
|
||||
final bgSecondary = isDark ? const Color(0xFF0B1120) : const Color(0xFFF8FAFC);
|
||||
final surfaceCard = isDark ? const Color(0xFF0F172A) : const Color(0xFFFFFFFF);
|
||||
final bgTertiary = isDark ? const Color(0xFF1E293B) : const Color(0xFFF1F5F9);
|
||||
final borderDefault = isDark ? const Color(0xFF334155) : const Color(0xFFE2E8F0);
|
||||
final textPrimary = isDark ? const Color(0xFFF8FAFC) : const Color(0xFF0F172A);
|
||||
final textSecondary = isDark ? const Color(0xFF94A3B8) : const Color(0xFF475569);
|
||||
final textMuted = isDark ? const Color(0xFF64748B) : const Color(0xFF94A3B8);
|
||||
final textInverse = isDark ? const Color(0xFF0F172A) : const Color(0xFFFFFFFF);
|
||||
final accentPrimary = isDark ? const Color(0xFFD4AF37) : const Color(0xFF1F2937);
|
||||
final goldAccent = isDark ? const Color(0xFFD4AF37) : const Color(0xFFF59E0B);
|
||||
final profitGreen = isDark ? const Color(0xFF4ADE80) : const Color(0xFF16A34A);
|
||||
final profitGreenBg = isDark ? const Color(0xFF052E16) : const Color(0xFFF0FDF4);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: colorScheme.background,
|
||||
backgroundColor: bgSecondary,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
backgroundColor: isDark ? const Color(0xFF0F172A) : const Color(0xFFFFFFFF),
|
||||
elevation: 0,
|
||||
scrolledUnderElevation: 0,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: colorScheme.onSurface),
|
||||
icon: Icon(LucideIcons.arrowLeft, color: textPrimary, size: 20),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
title: Text(
|
||||
'资金划转',
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
'账户划转',
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: textPrimary,
|
||||
),
|
||||
),
|
||||
centerTitle: true,
|
||||
@@ -162,135 +176,49 @@ class _TransferPageState extends State<TransferPage> {
|
||||
body: Consumer<AssetProvider>(
|
||||
builder: (context, provider, _) {
|
||||
return SingleChildScrollView(
|
||||
padding: AppSpacing.pagePadding,
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 32),
|
||||
child: Column(
|
||||
children: [
|
||||
// 第一个卡片位置 - 带动画
|
||||
TweenAnimationBuilder<double>(
|
||||
tween: Tween(begin: 0, end: 1),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
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,
|
||||
),
|
||||
);
|
||||
},
|
||||
// --- Transfer Direction Card ---
|
||||
_buildTransferDirectionCard(
|
||||
colorScheme: colorScheme,
|
||||
isDark: isDark,
|
||||
surfaceCard: surfaceCard,
|
||||
borderDefault: borderDefault,
|
||||
textPrimary: textPrimary,
|
||||
textSecondary: textSecondary,
|
||||
textMuted: textMuted,
|
||||
textInverse: textInverse,
|
||||
accentPrimary: accentPrimary,
|
||||
),
|
||||
|
||||
// 方向切换按钮(固定在中间)
|
||||
GestureDetector(
|
||||
onTap: _toggleDirection,
|
||||
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,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// --- Amount Section ---
|
||||
_buildAmountSection(
|
||||
isDark: isDark,
|
||||
bgTertiary: bgTertiary,
|
||||
textPrimary: textPrimary,
|
||||
textSecondary: textSecondary,
|
||||
textMuted: textMuted,
|
||||
goldAccent: goldAccent,
|
||||
),
|
||||
|
||||
// 第二个卡片位置 - 带动画
|
||||
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('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,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// --- Tips Card ---
|
||||
_buildTipsCard(
|
||||
profitGreen: profitGreen,
|
||||
profitGreenBg: profitGreenBg,
|
||||
),
|
||||
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// 金额输入卡片
|
||||
_buildAmountSection(colorScheme, isDark),
|
||||
|
||||
SizedBox(height: AppSpacing.lg),
|
||||
|
||||
// 确认按钮
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: NeonButton(
|
||||
text: _isLoading ? '处理中...' : '确认划转',
|
||||
icon: _isLoading ? null : LucideIcons.arrowRightLeft,
|
||||
type: NeonButtonType.primary,
|
||||
onPressed: _isLoading ? null : _doTransfer,
|
||||
height: 52,
|
||||
showGlow: true,
|
||||
),
|
||||
// --- Confirm Button ---
|
||||
_buildConfirmButton(
|
||||
accentPrimary: accentPrimary,
|
||||
textInverse: textInverse,
|
||||
),
|
||||
|
||||
SizedBox(height: AppSpacing.md),
|
||||
|
||||
// 划转说明
|
||||
_buildTips(colorScheme),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -299,275 +227,345 @@ class _TransferPageState extends State<TransferPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 账户卡片
|
||||
Widget _buildAccountCard({
|
||||
/// Transfer direction card with source, swap, destination
|
||||
Widget _buildTransferDirectionCard({
|
||||
required ColorScheme colorScheme,
|
||||
required bool isDark,
|
||||
required Color surfaceCard,
|
||||
required Color borderDefault,
|
||||
required Color textPrimary,
|
||||
required Color textSecondary,
|
||||
required Color textMuted,
|
||||
required Color textInverse,
|
||||
required Color accentPrimary,
|
||||
}) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: surfaceCard,
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
border: Border.all(color: borderDefault.withOpacity(0.6)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Source account
|
||||
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: _buildAccountRow(
|
||||
key: ValueKey('src-$_direction'),
|
||||
label: '从',
|
||||
accountName: _fromLabel,
|
||||
balance: _fromBalance,
|
||||
isDark: isDark,
|
||||
textMuted: textMuted,
|
||||
textPrimary: textPrimary,
|
||||
textSecondary: textSecondary,
|
||||
),
|
||||
),
|
||||
|
||||
// Swap button
|
||||
GestureDetector(
|
||||
onTap: _toggleDirection,
|
||||
child: Container(
|
||||
width: 36,
|
||||
height: 36,
|
||||
margin: const EdgeInsets.symmetric(vertical: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: accentPrimary,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
LucideIcons.arrowUpDown,
|
||||
size: 18,
|
||||
color: textInverse,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Destination account
|
||||
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: _buildAccountRow(
|
||||
key: ValueKey('dst-$_direction'),
|
||||
label: '到',
|
||||
accountName: _toLabel,
|
||||
balance: _toBalance,
|
||||
isDark: isDark,
|
||||
textMuted: textMuted,
|
||||
textPrimary: textPrimary,
|
||||
textSecondary: textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Single account row inside the direction card
|
||||
Widget _buildAccountRow({
|
||||
Key? key,
|
||||
required String label,
|
||||
required String accountName,
|
||||
required String balance,
|
||||
required bool isDark,
|
||||
required ColorScheme colorScheme,
|
||||
required Color textMuted,
|
||||
required Color textPrimary,
|
||||
required Color textSecondary,
|
||||
}) {
|
||||
return Container(
|
||||
key: key,
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? colorScheme.surfaceContainer : colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
border: Border.all(
|
||||
color: colorScheme.outlineVariant.withOpacity(0.15),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.sm, vertical: AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: AppSpacing.sm),
|
||||
Text(
|
||||
accountName,
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'可用余额',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
Text(
|
||||
'$balance USDT',
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 金额输入区域
|
||||
Widget _buildAmountSection(ColorScheme colorScheme, bool isDark) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? colorScheme.surfaceContainer : colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
border: Border.all(
|
||||
color: colorScheme.outlineVariant.withOpacity(0.15),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Label row
|
||||
Text(
|
||||
'划转金额',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
label,
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: textMuted,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
// 金额输入行
|
||||
const SizedBox(height: 8),
|
||||
// Account name + balance row
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _amountController,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,8}')),
|
||||
],
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: '0.00',
|
||||
hintStyle: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: colorScheme.onSurfaceVariant.withOpacity(0.3),
|
||||
),
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
isDense: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 4),
|
||||
child: Text(
|
||||
'USDT',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
// 快捷按钮行
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'可用: ${_availableBalance}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
_buildQuickButton('25%', 0.25, colorScheme),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
_buildQuickButton('50%', 0.50, colorScheme),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
_buildQuickButton('75%', 0.75, colorScheme),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
_buildQuickButton('全部', 1.0, colorScheme),
|
||||
],
|
||||
),
|
||||
if (_direction == 2) ...[
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
Container(
|
||||
padding: EdgeInsets.all(AppSpacing.sm),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorScheme.warning.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: Row(
|
||||
// Account name with icon
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
LucideIcons.triangleAlert,
|
||||
size: 14,
|
||||
color: AppColorScheme.warning,
|
||||
label == '从' ? LucideIcons.wallet : LucideIcons.repeat,
|
||||
size: 18,
|
||||
color: textSecondary,
|
||||
),
|
||||
SizedBox(width: AppSpacing.xs),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'仅支持 USDT 资产划转到资金账户',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: AppColorScheme.warning,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
accountName,
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Balance
|
||||
Text(
|
||||
'\u00A5 ${_formatBalance(balance)}',
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Format balance for display
|
||||
String _formatBalance(String balance) {
|
||||
final val = double.tryParse(balance);
|
||||
if (val == null) return '0.00';
|
||||
return val.toStringAsFixed(2);
|
||||
}
|
||||
|
||||
/// Amount input section
|
||||
Widget _buildAmountSection({
|
||||
required bool isDark,
|
||||
required Color bgTertiary,
|
||||
required Color textPrimary,
|
||||
required Color textSecondary,
|
||||
required Color textMuted,
|
||||
required Color goldAccent,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Label row: "划转金额" + "全部划转"
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'划转金额',
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textSecondary,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => _setQuickAmount(1.0),
|
||||
child: Text(
|
||||
'全部划转',
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: goldAccent,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 快捷百分比按钮
|
||||
Widget _buildQuickButton(String label, double percent, ColorScheme colorScheme) {
|
||||
return GestureDetector(
|
||||
onTap: () => _setQuickAmount(percent),
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.sm, vertical: AppSpacing.xs),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
const SizedBox(height: 12),
|
||||
|
||||
/// 划转说明
|
||||
Widget _buildTips(ColorScheme colorScheme) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(AppRadius.md),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'划转说明',
|
||||
style: GoogleFonts.spaceGrotesk(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
SizedBox(height: AppSpacing.sm),
|
||||
_buildTipItem('资金账户用于充提,交易账户用于买卖币种', colorScheme),
|
||||
_buildTipItem('划转操作即时到账,不可撤销', colorScheme),
|
||||
_buildTipItem('交易账户只有 USDT 可直接划转到资金账户', colorScheme),
|
||||
_buildTipItem('其他币种需先卖出换成 USDT 后才能划转', colorScheme),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTipItem(String text, ColorScheme colorScheme) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: AppSpacing.xs),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: 4,
|
||||
height: 4,
|
||||
margin: EdgeInsets.only(top: 6, right: AppSpacing.sm),
|
||||
// Amount input field
|
||||
GestureDetector(
|
||||
onTap: () => _focusNode.requestFocus(),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 56,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
shape: BoxShape.circle,
|
||||
color: bgTertiary,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
// Input
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _amountController,
|
||||
focusNode: _focusNode,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,8}')),
|
||||
],
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: textPrimary,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: '0.00',
|
||||
hintStyle: GoogleFonts.inter(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: textMuted,
|
||||
),
|
||||
border: InputBorder.none,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
isDense: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Suffix
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
'USDT',
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: textMuted,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Percent buttons
|
||||
Row(
|
||||
children: [
|
||||
_buildPercentButton('25%', 0.25, isDark, bgTertiary, textSecondary),
|
||||
const SizedBox(width: 8),
|
||||
_buildPercentButton('50%', 0.50, isDark, bgTertiary, textSecondary),
|
||||
const SizedBox(width: 8),
|
||||
_buildPercentButton('75%', 0.75, isDark, bgTertiary, textSecondary),
|
||||
const SizedBox(width: 8),
|
||||
_buildPercentButton('100%', 1.0, isDark, bgTertiary, textSecondary),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Percent quick button
|
||||
Widget _buildPercentButton(String label, double percent, bool isDark, Color bgTertiary, Color textSecondary) {
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => _setQuickAmount(percent),
|
||||
child: Container(
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: bgTertiary,
|
||||
borderRadius: BorderRadius.circular(AppRadius.sm),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
label,
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Tips card with green background
|
||||
Widget _buildTipsCard({
|
||||
required Color profitGreen,
|
||||
required Color profitGreenBg,
|
||||
}) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: profitGreenBg,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
LucideIcons.info,
|
||||
size: 16,
|
||||
color: profitGreen,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
'划转即时到账,无需手续费',
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: profitGreen,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -575,4 +573,43 @@ class _TransferPageState extends State<TransferPage> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Confirm button
|
||||
Widget _buildConfirmButton({
|
||||
required Color accentPrimary,
|
||||
required Color textInverse,
|
||||
}) {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
height: 52,
|
||||
child: GestureDetector(
|
||||
onTap: _isLoading ? null : _doTransfer,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: accentPrimary,
|
||||
borderRadius: BorderRadius.circular(AppRadius.lg),
|
||||
),
|
||||
child: Center(
|
||||
child: _isLoading
|
||||
? SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(textInverse),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
'确认划转',
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: textInverse,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user