diff --git a/frontend/mobile-app/lib/features/authorization/presentation/widgets/stickman_race_widget.dart b/frontend/mobile-app/lib/features/authorization/presentation/widgets/stickman_race_widget.dart index e3b1d424..46ab7391 100644 --- a/frontend/mobile-app/lib/features/authorization/presentation/widgets/stickman_race_widget.dart +++ b/frontend/mobile-app/lib/features/authorization/presentation/widgets/stickman_race_widget.dart @@ -234,99 +234,99 @@ class _StickmanRaceWidgetState extends State // 添加上下弹跳效果 final bounce = _bounceController.value * 3; - // 计算可用宽度:屏幕宽度 - 页面padding(32) - 容器padding(32) - 红旗区域(40) - 火柴人宽度一半(30) + // 计算可用宽度:屏幕宽度 - 页面padding(32) - 容器padding(32) - 红旗区域(40) // 让火柴人在100%时正好到达红旗位置 final screenWidth = MediaQuery.of(context).size.width; final containerWidth = screenWidth - 32 - 32; // 页面padding + 容器padding - final stickmanHalfWidth = 30.0; // 火柴人宽度的一半,用于居中对齐 - final flagAreaWidth = 40.0; // 红旗区域宽度(红旗在right:8位置,图标24+边距) + final stickmanWidth = 60.0; // 火柴人+数量标签的宽度 + final flagAreaWidth = 40.0; // 红旗区域宽度 final nicknameAreaWidth = 65.0; // 昵称区域宽度 - final availableWidth = containerWidth - flagAreaWidth - stickmanHalfWidth - nicknameAreaWidth; - final leftPosition = nicknameAreaWidth + availableWidth * horizontalProgress; + final gap = 4.0; // 昵称和火柴人之间的最小间距 + // 火柴人可移动的范围:从昵称右边开始到红旗位置 + final availableWidth = containerWidth - nicknameAreaWidth - gap - stickmanWidth - flagAreaWidth; + final stickmanLeftPosition = nicknameAreaWidth + gap + availableWidth * horizontalProgress; return Positioned( left: 0, top: verticalPosition - bounce, - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - // 昵称标签 - 固定在左边 - SizedBox( - width: nicknameAreaWidth, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), - decoration: BoxDecoration( - color: data.isCurrentUser - ? const Color(0xFFD4AF37).withValues(alpha: 0.2) - : Colors.white.withValues(alpha: 0.8), - borderRadius: BorderRadius.circular(4), - border: data.isCurrentUser - ? Border.all(color: const Color(0xFFD4AF37), width: 1) - : null, + child: SizedBox( + width: containerWidth, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 昵称标签 - 固定在左边,与数量标签同一水平高度 + SizedBox( + width: nicknameAreaWidth, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), + decoration: BoxDecoration( + color: data.isCurrentUser + ? const Color(0xFFD4AF37).withValues(alpha: 0.2) + : Colors.white.withValues(alpha: 0.8), + borderRadius: BorderRadius.circular(8), + border: data.isCurrentUser + ? Border.all(color: const Color(0xFFD4AF37), width: 1) + : null, + ), + child: Text( + data.nickname, + style: TextStyle( + fontSize: 9, + fontFamily: 'Inter', + fontWeight: + data.isCurrentUser ? FontWeight.w600 : FontWeight.w400, + color: data.isCurrentUser + ? const Color(0xFFD4AF37) + : const Color(0xFF5D4037), + ), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, + ), ), - child: Text( - data.nickname, - style: TextStyle( - fontSize: 9, - fontFamily: 'Inter', - fontWeight: - data.isCurrentUser ? FontWeight.w600 : FontWeight.w400, + ), + // 间隔 + 火柴人位置 + SizedBox( + width: stickmanLeftPosition - nicknameAreaWidth, + ), + // 火柴人和数量标签 + Column( + mainAxisSize: MainAxisSize.min, + children: [ + // 完成数量标签 + Container( + constraints: const BoxConstraints(maxWidth: 60), + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: data.isCurrentUser + ? const Color(0xFFD4AF37) + : const Color(0xFF8B5A2B), + borderRadius: BorderRadius.circular(8), + ), + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + '${_formatNumber(data.completedCount)}棵', + style: const TextStyle( + fontSize: 9, + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + ), + ), + const SizedBox(height: 2), + // 火柴人动画 + RunningStickman( + size: 36, color: data.isCurrentUser ? const Color(0xFFD4AF37) : const Color(0xFF5D4037), ), - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - ), - ), - ), - // 火柴人和数量标签 - SizedBox( - width: leftPosition - nicknameAreaWidth + stickmanHalfWidth * 2, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - children: [ - // 完成数量标签 - Container( - constraints: const BoxConstraints(maxWidth: 60), - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: data.isCurrentUser - ? const Color(0xFFD4AF37) - : const Color(0xFF8B5A2B), - borderRadius: BorderRadius.circular(8), - ), - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - '${_formatNumber(data.completedCount)}棵', - style: const TextStyle( - fontSize: 9, - fontFamily: 'Inter', - fontWeight: FontWeight.w600, - color: Colors.white, - ), - ), - ), - ), - const SizedBox(height: 2), - // 火柴人动画 - RunningStickman( - size: 36, - color: data.isCurrentUser - ? const Color(0xFFD4AF37) - : const Color(0xFF5D4037), - ), - ], - ), ], ), - ), - ], + ], + ), ), ); },