// Author: fruit.com.cn import 'package:flutter/material.dart'; import '../../../core/formatting/count_format.dart'; import '../../../core/theme/app_colors.dart'; const double _defaultButtonSize = 44; const double _defaultIconSize = 32; const double _defaultCountFont = 12; const double _defaultIconCountGap = 2; const double _defaultItemGap = 24; /// 互动栏单项:图标、计数与点击。 class InteractionRailItem { const InteractionRailItem({ required this.key, required this.label, required this.onTap, this.asset, this.icon, this.count, this.countKey, this.selected = false, this.selectedColor = AppColors.blue, this.mirrorIcon = false, }) : assert((asset == null) != (icon == null)); final Key key; final String? asset; final IconData? icon; final String label; final VoidCallback onTap; final int? count; final Key? countKey; final bool selected; final Color selectedColor; /// 水平镜像图标(分享弯箭头用 reply 镜像得到)。 final bool mirrorIcon; } /// 播放页与首页 feed 共用的右侧互动栏:收藏/评论/喜欢/分享。 class InteractionRail extends StatelessWidget { const InteractionRail({ super.key, required this.items, this.itemGap = _defaultItemGap, this.buttonSize = _defaultButtonSize, this.iconSize = _defaultIconSize, this.countFontSize = _defaultCountFont, this.iconCountGap = _defaultIconCountGap, }); final List items; final double itemGap; final double buttonSize; final double iconSize; final double countFontSize; final double iconCountGap; @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ for (var index = 0; index < items.length; index++) ...[ if (index > 0) SizedBox(height: itemGap), _RailButton( item: items[index], buttonSize: buttonSize, iconSize: iconSize, countFontSize: countFontSize, iconCountGap: iconCountGap, ), ], ], ); } } class _RailButton extends StatelessWidget { const _RailButton({ required this.item, required this.buttonSize, required this.iconSize, required this.countFontSize, required this.iconCountGap, }); final InteractionRailItem item; final double buttonSize; final double iconSize; final double countFontSize; final double iconCountGap; @override Widget build(BuildContext context) { final tint = item.selected ? item.selectedColor : AppColors.onPrimary; return Column( key: item.key, mainAxisSize: MainAxisSize.min, children: [ SizedBox.square( dimension: buttonSize, child: IconButton( onPressed: item.onTap, padding: EdgeInsets.zero, icon: item.asset != null ? Image.asset( item.asset!, width: iconSize, height: iconSize, fit: BoxFit.contain, color: tint, colorBlendMode: BlendMode.srcIn, ) : Transform.flip( flipX: item.mirrorIcon, child: Icon(item.icon, size: iconSize, color: tint), ), ), ), SizedBox(height: iconCountGap), Text( item.count == null ? item.label : formatInteractionCount(item.count!), key: item.countKey, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( color: AppColors.onPrimary, height: 1, fontSize: countFontSize, fontWeight: FontWeight.w600, shadows: const [ Shadow(blurRadius: 6, color: AppColors.mediaBlack), ], ), ), ], ); } }