Files
monisuo/flutter_monisuo/lib/ui/components/glass_panel.dart
sion df0e8beba9 feat(ui): 应用新设计系统到 Flutter 项目
- 更新颜色系统为 Material Design 3
  * Primary: #72dcff (青色)
  * Secondary: #dd8bfb (紫色)
  * Tertiary: #afffd1 (绿色)

- 创建新的 UI 组件
  * GlassPanel: 毛玻璃效果面板
  * NeonGlow: 霓虹光效组件
  * GradientButton: 渐变按钮组件

- 更新所有页面样式
  * 交易页面 (trade_page.dart)
  * 行情页面 (market_page.dart)
  * 资产页面 (asset_page.dart)
  * 我的页面 (mine_page.dart)
  * 订单页面 (orders_page.dart)

- 支持深色和浅色主题
- 所有 UI 文字使用中文
- 保持现有 API 接口不变

变更统计:
- 9 个文件修改
- 1,893 行新增
- 691 行删除
- 3 个新组件
2026-03-24 02:16:19 +08:00

316 lines
7.9 KiB
Dart

import 'dart:ui';
import 'package:flutter/material.dart';
import '../../core/theme/app_color_scheme.dart';
import '../../core/theme/app_spacing.dart';
/// GlassPanel - 毛玻璃效果面板
///
/// Material Design 3 风格的毛玻璃效果组件
/// 用于卡片、弹窗、底部抽屉等需要毛玻璃效果的容器
///
/// 示例:
/// ```dart
/// GlassPanel(
/// child: Text('内容'),
/// )
/// ```
class GlassPanel extends StatelessWidget {
/// 子组件
final Widget child;
/// 模糊程度,默认 20.0
final double blur;
/// 背景色,默认使用 GlassPanel 背景色
final Color? backgroundColor;
/// 边框色,默认使用 GlassPanel 边框色
final Color? borderColor;
/// 圆角,默认特大圆角
final BorderRadius? borderRadius;
/// 内边距
final EdgeInsetsGeometry? padding;
/// 外边距
final EdgeInsetsGeometry? margin;
/// 宽度
final double? width;
/// 高度
final double? height;
/// 是否显示边框
final bool showBorder;
const GlassPanel({
super.key,
required this.child,
this.blur = 20.0,
this.backgroundColor,
this.borderColor,
this.borderRadius,
this.padding,
this.margin,
this.width,
this.height,
this.showBorder = true,
});
@override
Widget build(BuildContext context) {
final bgColor = backgroundColor ?? AppColorScheme.glassPanelBackground;
final brColor = borderColor ?? AppColorScheme.glassPanelBorder;
final br = borderRadius ?? BorderRadius.circular(AppRadius.xl);
Widget content = ClipRRect(
borderRadius: br,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
child: Container(
width: width,
height: height,
padding: padding ?? EdgeInsets.all(AppSpacing.md),
decoration: BoxDecoration(
color: bgColor,
borderRadius: br,
border: showBorder
? Border.all(
color: brColor,
width: 1,
)
: null,
),
child: child,
),
),
);
if (margin != null) {
content = Padding(
padding: margin!,
child: content,
);
}
return content;
}
}
/// GlassCard - 带毛玻璃效果的卡片
///
/// 用于列表项、信息展示等场景
/// 预设了常用配置,简化使用
class GlassCard extends StatelessWidget {
/// 子组件
final Widget child;
/// 点击回调
final VoidCallback? onTap;
/// 长按回调
final VoidCallback? onLongPress;
/// 内边距
final EdgeInsetsGeometry? padding;
/// 外边距
final EdgeInsetsGeometry? margin;
/// 圆角
final BorderRadius? borderRadius;
/// 是否显示霓虹光效
final bool showNeonGlow;
/// 霓虹光效颜色
final Color? neonGlowColor;
const GlassCard({
super.key,
required this.child,
this.onTap,
this.onLongPress,
this.padding,
this.margin,
this.borderRadius,
this.showNeonGlow = false,
this.neonGlowColor,
});
@override
Widget build(BuildContext context) {
final br = borderRadius ?? BorderRadius.circular(AppRadius.xl);
final glowColor = neonGlowColor ?? AppColorScheme.neonGlowPrimary;
Widget card = GlassPanel(
padding: padding ?? EdgeInsets.all(AppSpacing.md),
margin: margin,
borderRadius: br,
child: child,
);
if (showNeonGlow) {
card = Container(
decoration: BoxDecoration(
borderRadius: br,
boxShadow: [
BoxShadow(
color: glowColor,
blurRadius: 15,
spreadRadius: 0,
),
],
),
child: card,
);
}
if (onTap != null || onLongPress != null) {
return GestureDetector(
onTap: onTap,
onLongPress: onLongPress,
child: card,
);
}
return card;
}
}
/// GlassBottomSheet - 毛玻璃底部抽屉
///
/// 用于弹出的底部面板
class GlassBottomSheet extends StatelessWidget {
/// 子组件
final Widget child;
/// 标题
final String? title;
/// 是否显示关闭按钮
final bool showCloseButton;
/// 内边距
final EdgeInsetsGeometry? padding;
const GlassBottomSheet({
super.key,
required this.child,
this.title,
this.showCloseButton = true,
this.padding,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: AppColorScheme.glassPanelBackground,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(AppRadius.xxl),
),
border: Border.all(
color: AppColorScheme.glassPanelBorder,
),
),
child: ClipRRect(
borderRadius: const BorderRadius.vertical(
top: Radius.circular(AppRadius.xxl),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 顶部拖动条
Container(
margin: const EdgeInsets.only(top: 12, bottom: 8),
width: 40,
height: 4,
decoration: BoxDecoration(
color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.5),
borderRadius: BorderRadius.circular(2),
),
),
// 标题栏
if (title != null || showCloseButton)
Padding(
padding: EdgeInsets.fromLTRB(
AppSpacing.lg,
AppSpacing.sm,
AppSpacing.sm,
AppSpacing.md,
),
child: Row(
children: [
if (title != null)
Expanded(
child: Text(
title!,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColorScheme.darkOnSurface,
),
),
),
if (showCloseButton)
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
padding: EdgeInsets.all(AppSpacing.sm),
decoration: BoxDecoration(
color: AppColorScheme.darkOutlineVariant
.withValues(alpha: 0.2),
shape: BoxShape.circle,
),
child: const Icon(
Icons.close,
size: 18,
color: AppColorScheme.darkOnSurfaceVariant,
),
),
),
],
),
),
// 内容
Padding(
padding: padding ??
EdgeInsets.fromLTRB(
AppSpacing.lg,
0,
AppSpacing.lg,
AppSpacing.xl,
),
child: child,
),
],
),
),
),
);
}
/// 显示底部抽屉
static Future<T?> show<T>({
required BuildContext context,
required Widget Function(BuildContext) builder,
bool isScrollControlled = false,
bool isDismissible = true,
bool enableDrag = true,
}) {
return showModalBottomSheet<T>(
context: context,
isScrollControlled: isScrollControlled,
isDismissible: isDismissible,
enableDrag: enableDrag,
backgroundColor: Colors.transparent,
builder: builder,
);
}
}