import 'package:flutter/material.dart'; import '../../core/theme/app_color_scheme.dart'; import '../../core/theme/app_spacing.dart'; /// NeonGlow - 霓虹光效组件 /// /// Material Design 3 风格的霓虹光效 /// 用于按钮、卡片、图标等需要突出显示的元素 /// /// 光效类型: /// - Primary: 青色光效 (#72dcff) /// - Secondary: 紫色光效 (#dd8bfb) /// - Tertiary: 绿色光效 (#afffd1) /// - Error: 红色光效 (#ff716c) class NeonGlow extends StatelessWidget { /// 子组件 final Widget child; /// 光效颜色 final Color glowColor; /// 模糊半径,默认 15.0 final double blurRadius; /// 扩散半径,默认 0.0 final double spreadRadius; /// 圆角 final BorderRadius? borderRadius; const NeonGlow({ super.key, required this.child, required this.glowColor, this.blurRadius = 15.0, this.spreadRadius = 0.0, this.borderRadius, }); /// Primary 霓虹光效 (青色) factory NeonGlow.primary({ Key? key, required Widget child, double blurRadius = 15.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.neonGlowPrimary, blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } /// Secondary 霓虹光效 (紫色) factory NeonGlow.secondary({ Key? key, required Widget child, double blurRadius = 15.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.neonGlowSecondary, blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } /// Tertiary 霓虹光效 (绿色) factory NeonGlow.tertiary({ Key? key, required Widget child, double blurRadius = 20.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.neonGlowTertiary, blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } /// Error 霓虹光效 (红色) factory NeonGlow.error({ Key? key, required Widget child, double blurRadius = 15.0, BorderRadius? borderRadius, }) { return NeonGlow( key: key, glowColor: AppColorScheme.down.withOpacity(0.3), blurRadius: blurRadius, borderRadius: borderRadius, child: child, ); } @override Widget build(BuildContext context) { final br = borderRadius ?? BorderRadius.circular(AppRadius.xl); return Container( decoration: BoxDecoration( borderRadius: br, boxShadow: [ BoxShadow( color: glowColor, blurRadius: blurRadius, spreadRadius: spreadRadius, ), ], ), child: child, ); } } /// NeonButton - 带霓虹光效的按钮 /// /// 预设了常用配置,简化使用 class NeonButton extends StatefulWidget { /// 按钮文本 final String text; /// 点击回调 final VoidCallback? onPressed; /// 按钮类型 final NeonButtonType type; /// 是否显示光效 final bool showGlow; /// 图标 final IconData? icon; /// 是否加载中 final bool isLoading; /// 按钮宽度 final double? width; /// 按钮高度,默认 48 final double height; const NeonButton({ super.key, required this.text, this.onPressed, this.type = NeonButtonType.primary, this.showGlow = true, this.icon, this.isLoading = false, this.width, this.height = 48, }); @override State createState() => _NeonButtonState(); } class _NeonButtonState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _scaleAnimation; bool _isPressed = false; @override void initState() { super.initState(); _controller = AnimationController( duration: const Duration(milliseconds: 150), vsync: this, ); _scaleAnimation = Tween(begin: 1.0, end: 0.95).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); } @override void dispose() { _controller.dispose(); super.dispose(); } void _onTapDown(TapDownDetails details) { setState(() => _isPressed = true); _controller.forward(); } void _onTapUp(TapUpDetails details) { setState(() => _isPressed = false); _controller.reverse(); } void _onTapCancel() { setState(() => _isPressed = false); _controller.reverse(); } Color get _backgroundColor { final isDark = Theme.of(context).brightness == Brightness.dark; final colorScheme = Theme.of(context).colorScheme; switch (widget.type) { case NeonButtonType.primary: return colorScheme.primary; case NeonButtonType.secondary: return colorScheme.secondary; case NeonButtonType.tertiary: return AppColorScheme.getUpColor(isDark); case NeonButtonType.error: return AppColorScheme.down; case NeonButtonType.outline: return Colors.transparent; } } Color get _foregroundColor { final isDark = Theme.of(context).brightness == Brightness.dark; final colorScheme = Theme.of(context).colorScheme; switch (widget.type) { case NeonButtonType.primary: return isDark ? AppColorScheme.darkOnPrimary : const Color(0xFFFFFFFF); case NeonButtonType.secondary: return isDark ? AppColorScheme.darkOnSecondary : const Color(0xFFFFFFFF); case NeonButtonType.tertiary: return isDark ? AppColorScheme.darkOnTertiary : const Color(0xFFFFFFFF); case NeonButtonType.error: return const Color(0xFFFFFFFF); case NeonButtonType.outline: return colorScheme.primary; } } Color get _glowColor { final isDark = Theme.of(context).brightness == Brightness.dark; final colorScheme = Theme.of(context).colorScheme; switch (widget.type) { case NeonButtonType.primary: return colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08); case NeonButtonType.secondary: return colorScheme.secondary.withOpacity(isDark ? 0.15 : 0.08); case NeonButtonType.tertiary: return AppColorScheme.getUpBackgroundColor(isDark, opacity: isDark ? 0.2 : 0.1); case NeonButtonType.error: return AppColorScheme.down.withOpacity(0.3); case NeonButtonType.outline: return colorScheme.primary.withOpacity(isDark ? 0.15 : 0.08); } } LinearGradient? get _gradient { // 【优化】移除所有渐变效果,改为纯色背景,提升专业金融感 return null; } @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; final isDark = Theme.of(context).brightness == Brightness.dark; final button = GestureDetector( onTapDown: widget.onPressed != null ? _onTapDown : null, onTapUp: widget.onPressed != null ? _onTapUp : null, onTapCancel: widget.onPressed != null ? _onTapCancel : null, onTap: widget.isLoading ? null : widget.onPressed, child: ScaleTransition( scale: _scaleAnimation, child: Container( width: widget.width, height: widget.height, decoration: BoxDecoration( gradient: _gradient, color: _gradient == null ? _backgroundColor : null, borderRadius: BorderRadius.circular( widget.type == NeonButtonType.outline ? AppRadius.md : AppRadius.lg, ), border: widget.type == NeonButtonType.outline ? Border.all( color: colorScheme.outlineVariant.withOpacity(0.3), ) : null, ), child: Center( child: widget.isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(_foregroundColor), ), ) : Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ if (widget.icon != null) ...[ Icon(widget.icon, size: 18, color: _foregroundColor), SizedBox(width: AppSpacing.sm), ], Text( widget.text, style: TextStyle( color: _foregroundColor, fontSize: 16, fontWeight: FontWeight.w600, ), ), ], ), ), ), ), ); if (widget.showGlow && widget.type != NeonButtonType.outline) { return NeonGlow( glowColor: _glowColor, borderRadius: BorderRadius.circular( widget.type == NeonButtonType.outline ? AppRadius.md : AppRadius.lg, ), child: button, ); } return button; } } /// 按钮类型 enum NeonButtonType { /// 主要按钮 (青色) primary, /// 次要按钮 (紫色) secondary, /// 成功按钮 (绿色) tertiary, /// 危险按钮 (红色) error, /// 边框按钮 outline, } /// NeonIcon - 带霓虹光效的图标 class NeonIcon extends StatelessWidget { /// 图标 final IconData icon; /// 图标大小 final double size; /// 图标颜色 final Color color; /// 光效颜色,默认使用图标颜色 final Color? glowColor; /// 光效模糊半径 final double glowBlur; const NeonIcon({ super.key, required this.icon, this.size = 24, required this.color, this.glowColor, this.glowBlur = 10, }); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: glowColor ?? color.withValues(alpha: 0.5), blurRadius: glowBlur, spreadRadius: 0, ), ], ), child: Icon(icon, size: size, color: color), ); } }