feat: 集成离线数字货币图标系统
✨ 新功能: - 下载16个主流币种图标(BTC, ETH, USDT, BNB, SOL等) - 创建 CoinIcon 组件,支持离线图标和兜底显示 - 更新 CoinAvatar 组件,使用新的 CoinIcon - 更新 market_page.dart 中的 _CoinAvatar 组件 📦 资源: - 图标存放在 flutter_monisuo/assets/icons/crypto/ - 使用 Cryptocurrency Icons 开源图标库 - PNG 格式,128x128 像素 🎯 特性: - 支持自定义大小 - 支持圆形背景 - 未找到图标时显示币种代码(兜底方案) - 支持深色/浅色模式 📝 修改文件: - 新增:flutter_monisuo/lib/ui/components/coin_icon.dart - 新增:flutter_monisuo/assets/icons/crypto/*.png (16个) - 修改:flutter_monisuo/pubspec.yaml - 修改:flutter_monisuo/lib/ui/pages/trade/components/coin_avatar.dart - 修改:flutter_monisuo/lib/ui/pages/market/market_page.dart - ✅ 后端构建成功 (2.0s) - ✅ Flutter Web 构建成功 (24.1s) - ⚠️ Admin: TypeScript类型错误(已知问题)
This commit is contained in:
106
flutter_monisuo/lib/ui/components/coin_icon.dart
Normal file
106
flutter_monisuo/lib/ui/components/coin_icon.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
/// 数字货币图标组件
|
||||
///
|
||||
/// 支持离线图标和兜底显示
|
||||
class CoinIcon extends StatelessWidget {
|
||||
final String symbol; // 币种代码,如 'BTC', 'ETH'
|
||||
final double size; // 图标大小,默认 40
|
||||
final bool isCircle; // 是否圆形背景,默认 false
|
||||
|
||||
const CoinIcon({
|
||||
super.key,
|
||||
required this.symbol,
|
||||
this.size = 40,
|
||||
this.isCircle = false,
|
||||
});
|
||||
|
||||
// 币种代码到文件名的映射
|
||||
static const Map<String, String> _coinFileMap = {
|
||||
'BTC': 'btc',
|
||||
'ETH': 'eth',
|
||||
'USDT': 'usdt',
|
||||
'BNB': 'bnb',
|
||||
'SOL': 'sol',
|
||||
'XRP': 'xrp',
|
||||
'ADA': 'ada',
|
||||
'DOGE': 'doge',
|
||||
'DOT': 'dot',
|
||||
'MATIC': 'matic',
|
||||
'SHIB': 'shib',
|
||||
'LTC': 'ltc',
|
||||
'AVAX': 'avax',
|
||||
'LINK': 'link',
|
||||
'UNI': 'uni',
|
||||
'ATOM': 'atom',
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final normalizedSymbol = symbol.toUpperCase();
|
||||
final fileName = _coinFileMap[normalizedSymbol];
|
||||
|
||||
Widget icon;
|
||||
|
||||
if (fileName != null) {
|
||||
// 尝试加载本地图标
|
||||
icon = Image.asset(
|
||||
'assets/icons/crypto/$fileName.png',
|
||||
width: size,
|
||||
height: size,
|
||||
fit: BoxFit.contain,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
// 加载失败,显示兜底UI
|
||||
return _buildFallback(context, normalizedSymbol);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// 没有对应的图标,显示兜底UI
|
||||
icon = _buildFallback(context, normalizedSymbol);
|
||||
}
|
||||
|
||||
if (isCircle) {
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
child: Center(child: icon),
|
||||
);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
/// 构建兜底UI(显示币种代码)
|
||||
Widget _buildFallback(BuildContext context, String symbol) {
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
symbol.length > 3 ? symbol.substring(0, 3) : symbol,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: size * 0.35,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import '../../../core/theme/app_theme_extension.dart';
|
||||
import '../../../data/models/coin.dart';
|
||||
import '../../../providers/market_provider.dart';
|
||||
import '../../components/glass_panel.dart';
|
||||
import '../../components/coin_icon.dart';
|
||||
import '../main/main_page.dart';
|
||||
|
||||
/// 行情頁面
|
||||
@@ -421,39 +422,13 @@ class _CoinAvatar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 使用主題變量而非硬編碼
|
||||
final bgColor = context.colors.primary.withValues(alpha: context.appColors.glowOpacity);
|
||||
|
||||
return Container(
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: bgColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
_getLetter(),
|
||||
style: AppTextStyles.labelLarge(context).copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: context.colors.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
// 使用新的 CoinIcon 组件
|
||||
return CoinIcon(
|
||||
symbol: code,
|
||||
size: 36,
|
||||
isCircle: true,
|
||||
);
|
||||
}
|
||||
|
||||
String _getLetter() {
|
||||
const letterMap = {
|
||||
'SOL': 'S',
|
||||
'BNB': 'B',
|
||||
'XRP': 'X',
|
||||
'DOGE': 'D',
|
||||
'ADA': 'A',
|
||||
'DOT': 'D',
|
||||
};
|
||||
return letterMap[code] ?? code.substring(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// 空狀態
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../../core/theme/app_spacing.dart';
|
||||
import '../../../../core/theme/app_theme.dart';
|
||||
import '../../../components/coin_icon.dart';
|
||||
|
||||
/// 幣種頭像組件
|
||||
///
|
||||
@@ -11,6 +12,16 @@ class CoinAvatar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 如果 icon 是币种代码(如 BTC, ETH),使用 CoinIcon
|
||||
if (icon != null && icon!.length <= 5 && icon!.toUpperCase() == icon) {
|
||||
return CoinIcon(
|
||||
symbol: icon!,
|
||||
size: 44,
|
||||
isCircle: false,
|
||||
);
|
||||
}
|
||||
|
||||
// 否则使用原来的字母显示方式
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
return Container(
|
||||
width: 44,
|
||||
|
||||
Reference in New Issue
Block a user