feat(recommend): 新增推荐频道页并恢复首页沉浸式信息流
- tab1 推荐页改为接口分类频道:频道导航可横滑,选中频道自动滚动到可视区,内容区左右滑动切换分类 - 精选频道:顶部固定高度 banner 轮播图 + 接口 tag 筛选的上新短剧横滑 + 其余短剧双列网格;其他分类三列网格 - 分类内容支持懒加载、下拉刷新与上拉分页加载 - 卡片角标文案与背景色取自接口 tag/tagColor,短剧标题统一白色 - 恢复 tab0 为沉浸式全屏视频首页及其三 inner-tab 顶导(搜索/礼物入口) - l10n 新增原创出品、立即观看、上新、编辑精选、全N集等多语言文案
This commit is contained in:
1 parent
a3f3481f4f
commit
c027acc91f
22 files changed
+2018
-318
No files matched your search
@@ -5,8 +5,10 @@ import 'package:flutter/material.dart';
|
||||
import '../../../core/formatting/count_format.dart';
|
||||
import '../../../core/theme/app_colors.dart';
|
||||
|
||||
const double _buttonSize = 44;
|
||||
const double _iconSize = 32;
|
||||
const double _defaultButtonSize = 44;
|
||||
const double _defaultIconSize = 32;
|
||||
const double _defaultCountFont = 12;
|
||||
const double _defaultIconCountGap = 2;
|
||||
const double _defaultItemGap = 24;
|
||||
|
||||
/// 互动栏单项:图标、计数与点击。
|
||||
@@ -21,6 +23,7 @@ class InteractionRailItem {
|
||||
this.countKey,
|
||||
this.selected = false,
|
||||
this.selectedColor = AppColors.blue,
|
||||
this.mirrorIcon = false,
|
||||
}) : assert((asset == null) != (icon == null));
|
||||
|
||||
final Key key;
|
||||
@@ -32,6 +35,9 @@ class InteractionRailItem {
|
||||
final Key? countKey;
|
||||
final bool selected;
|
||||
final Color selectedColor;
|
||||
|
||||
/// 水平镜像图标(分享弯箭头用 reply 镜像得到)。
|
||||
final bool mirrorIcon;
|
||||
}
|
||||
|
||||
/// 播放页与首页 feed 共用的右侧互动栏:收藏/评论/喜欢/分享。
|
||||
@@ -40,10 +46,18 @@ class InteractionRail extends StatelessWidget {
|
||||
super.key,
|
||||
required this.items,
|
||||
this.itemGap = _defaultItemGap,
|
||||
this.buttonSize = _defaultButtonSize,
|
||||
this.iconSize = _defaultIconSize,
|
||||
this.countFontSize = _defaultCountFont,
|
||||
this.iconCountGap = _defaultIconCountGap,
|
||||
});
|
||||
|
||||
final List<InteractionRailItem> items;
|
||||
final double itemGap;
|
||||
final double buttonSize;
|
||||
final double iconSize;
|
||||
final double countFontSize;
|
||||
final double iconCountGap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -52,7 +66,13 @@ class InteractionRail extends StatelessWidget {
|
||||
children: [
|
||||
for (var index = 0; index < items.length; index++) ...[
|
||||
if (index > 0) SizedBox(height: itemGap),
|
||||
_RailButton(item: items[index]),
|
||||
_RailButton(
|
||||
item: items[index],
|
||||
buttonSize: buttonSize,
|
||||
iconSize: iconSize,
|
||||
countFontSize: countFontSize,
|
||||
iconCountGap: iconCountGap,
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
@@ -60,53 +80,61 @@ class InteractionRail extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _RailButton extends StatelessWidget {
|
||||
const _RailButton({required this.item});
|
||||
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,
|
||||
dimension: buttonSize,
|
||||
child: IconButton(
|
||||
onPressed: item.onTap,
|
||||
padding: EdgeInsets.zero,
|
||||
icon: item.asset != null
|
||||
? Image.asset(
|
||||
item.asset!,
|
||||
width: _iconSize,
|
||||
height: _iconSize,
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
fit: BoxFit.contain,
|
||||
color: item.selected
|
||||
? item.selectedColor
|
||||
: AppColors.onPrimary,
|
||||
color: tint,
|
||||
colorBlendMode: BlendMode.srcIn,
|
||||
)
|
||||
: Icon(
|
||||
item.icon,
|
||||
size: _iconSize,
|
||||
color: item.selected
|
||||
? item.selectedColor
|
||||
: AppColors.onPrimary,
|
||||
: Transform.flip(
|
||||
flipX: item.mirrorIcon,
|
||||
child: Icon(item.icon, size: iconSize, color: tint),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
SizedBox(height: iconCountGap),
|
||||
Text(
|
||||
item.count == null ? item.label : formatInteractionCount(item.count!),
|
||||
key: item.countKey,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
color: AppColors.onPrimary,
|
||||
height: 1,
|
||||
fontSize: 12,
|
||||
fontSize: countFontSize,
|
||||
fontWeight: FontWeight.w600,
|
||||
shadows: [Shadow(blurRadius: 6, color: AppColors.mediaBlack)],
|
||||
shadows: const [
|
||||
Shadow(blurRadius: 6, color: AppColors.mediaBlack),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user