import 'package:flutter/material.dart'; /// 现代风格用户头像 /// - 无头像时:渐变背景 + 白色首字母 /// - 有头像时:显示网络图片 /// - 同一用户始终生成相同的渐变色 class UserAvatar extends StatelessWidget { final String? avatarUrl; final String displayName; final double radius; final VoidCallback? onTap; const UserAvatar({ super.key, this.avatarUrl, required this.displayName, this.radius = 20, this.onTap, }); /// 获取首字母 String get _initials { if (displayName.isEmpty) return '?'; final name = displayName.trim(); if (name.isEmpty) return '?'; // 中文名取第一个字 if (RegExp(r'[\u4e00-\u9fa5]').hasMatch(name)) { return name.substring(0, 1); } // 英文名取首字母大写 return name.substring(0, 1).toUpperCase(); } /// 现代渐变色方案 —— 每组两个颜色形成渐变 static const List> _gradients = [ [Color(0xFF667EEA), Color(0xFF764BA2)], // 靛蓝 → 紫 [Color(0xFF1DA1F2), Color(0xFF0070E0)], // Twitter 蓝 [Color(0xFFF093FB), Color(0xFFF5576C)], // 粉 → 玫红 [Color(0xFF4FACFE), Color(0xFF00F2FE)], // 天蓝 → 青 [Color(0xFF43E97B), Color(0xFF38F9D7)], // 绿 → 青 [Color(0xFFFA709A), Color(0xFFFEE140)], // 粉 → 金 [Color(0xFFA18CD1), Color(0xFFFBC2EB)], // 紫 → 粉 [Color(0xFFFDCB6E), Color(0xFFF0932B)], // 金 → 橙 [Color(0xFF6C5CE7), Color(0xFF0984E3)], // 紫 → 蓝 [Color(0xFFFD79A8), Color(0xFF6C5CE7)], // 粉 → 紫 ]; /// 基于用户名哈希选择渐变索引(同一用户名始终相同) int get _gradientIndex { final hash = displayName.hashCode.abs(); return hash % _gradients.length; } @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( width: radius * 2, height: radius * 2, decoration: BoxDecoration( shape: BoxShape.circle, gradient: avatarUrl != null && avatarUrl!.isNotEmpty ? null : LinearGradient( colors: _gradients[_gradientIndex], begin: Alignment.topLeft, end: Alignment.bottomRight, ), image: avatarUrl != null && avatarUrl!.isNotEmpty ? DecorationImage( image: NetworkImage(avatarUrl!), fit: BoxFit.cover, ) : null, ), child: avatarUrl == null || avatarUrl!.isEmpty ? Center( child: Text( _initials, style: TextStyle( fontSize: radius * 0.85, fontWeight: FontWeight.w600, color: Colors.white, height: 1.0, ), ), ) : null, ), ); } } /// 现代风格群组头像 /// - 使用群名首字符 + 渐变背景 class GroupAvatar extends StatelessWidget { final String? avatarUrl; final String groupName; final double radius; final VoidCallback? onTap; const GroupAvatar({ super.key, this.avatarUrl, required this.groupName, this.radius = 20, this.onTap, }); String get _initials { if (groupName.isEmpty) return '#'; final name = groupName.trim(); if (name.isEmpty) return '#'; if (RegExp(r'[\u4e00-\u9fa5]').hasMatch(name)) { return name.substring(0, 1); } return name.substring(0, 1).toUpperCase(); } static const List> _gradients = [ [Color(0xFF667EEA), Color(0xFF764BA2)], [Color(0xFF1DA1F2), Color(0xFF0070E0)], [Color(0xFFF093FB), Color(0xFFF5576C)], [Color(0xFF4FACFE), Color(0xFF00F2FE)], [Color(0xFF43E97B), Color(0xFF38F9D7)], [Color(0xFFFA709A), Color(0xFFFEE140)], [Color(0xFFA18CD1), Color(0xFFFBC2EB)], [Color(0xFFFDCB6E), Color(0xFFF0932B)], [Color(0xFF6C5CE7), Color(0xFF0984E3)], [Color(0xFFFD79A8), Color(0xFF6C5CE7)], ]; int get _gradientIndex { final hash = groupName.hashCode.abs(); return hash % _gradients.length; } @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( width: radius * 2, height: radius * 2, decoration: BoxDecoration( shape: BoxShape.circle, gradient: avatarUrl != null && avatarUrl!.isNotEmpty ? null : LinearGradient( colors: _gradients[_gradientIndex], begin: Alignment.topLeft, end: Alignment.bottomRight, ), image: avatarUrl != null && avatarUrl!.isNotEmpty ? DecorationImage( image: NetworkImage(avatarUrl!), fit: BoxFit.cover, ) : null, ), child: avatarUrl == null || avatarUrl!.isEmpty ? Center( child: Text( _initials, style: TextStyle( fontSize: radius * 0.85, fontWeight: FontWeight.w600, color: Colors.white, height: 1.0, ), ), ) : null, ), ); } }