fix(home): 调整播放量行内展示
This commit is contained in:
1 parent
c9fce7745e
commit
f7782aef14
8 files changed
+138
-114
No files matched your search
@@ -1115,5 +1115,5 @@ $ flutter test
|
||||
- 四类短剧卡片移除底板/描边,封面统一 8 圆角,网格行距 10、封底到标题 6;热剧/新剧/漫剧角标移至右上角异形丝带。
|
||||
- 标题下方恢复左对齐题材文字,使用 `|` 分隔、灰色小字,与封面状态角标保持独立。
|
||||
- 首页搜索栏到一级、一级到二级、二级到网格间距为 8/8/10;非精选 tab 直接以 10 衔接网格。
|
||||
- 播放量统一 spark 图标与 `w` 格式,整数无小数;首页、剧单、全部短剧、追剧共用。
|
||||
- 播放量移至标题行最右,使用 spark 图标与 12/w400 纯文字、`w` 格式,整数无小数;四类列表共用。
|
||||
- 全部短剧的地区、字幕、配音筛选 UI 已占位;以下接口待补:地区、字幕/配音筛选数据。
|
||||
@@ -87,6 +87,8 @@ abstract final class AppDimens {
|
||||
static const double cardTitleLineHeight = 1.3;
|
||||
static const double cardViewsFont = 11;
|
||||
static const double cardViewsIcon = 11;
|
||||
static const double cardPlayCountFont = 12;
|
||||
static const double cardPlayCountGap = 2;
|
||||
static const double cardGenreRibbonHeight = 20;
|
||||
static const double cardGenreRibbonRadius = 10;
|
||||
static const double cardGenreRibbonLeftInset = 8;
|
||||
|
||||
@@ -62,38 +62,6 @@ class FollowingGridCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: AppDimens.spaceXs,
|
||||
bottom: AppDimens.spaceXs,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
vertical: 2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.playerOverlayPill,
|
||||
borderRadius: BorderRadius.circular(AppDimens.pillRadius),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.auto_awesome_rounded,
|
||||
color: AppColors.textPrimary,
|
||||
size: AppDimens.cardViewsIcon,
|
||||
),
|
||||
Text(
|
||||
formatPlayCount(viewCount),
|
||||
key: Key('following-views-$dramaId'),
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardViewsFont,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (editing)
|
||||
Positioned(
|
||||
top: -6,
|
||||
@@ -116,17 +84,27 @@ class FollowingGridCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppDimens.cardCoverTitleGap),
|
||||
Text(
|
||||
title,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardTitleFont,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: AppDimens.cardTitleLineHeight,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardTitleFont,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: AppDimens.cardTitleLineHeight,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppDimens.spaceXs),
|
||||
_views(),
|
||||
],
|
||||
),
|
||||
if (tags.isNotEmpty) ...[
|
||||
const SizedBox(height: AppDimens.cardTitleTagGap),
|
||||
@@ -162,6 +140,30 @@ class FollowingGridCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _views() {
|
||||
return Row(
|
||||
key: Key('following-views-$dramaId'),
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.auto_awesome_rounded,
|
||||
color: AppColors.textPrimary,
|
||||
size: AppDimens.cardViewsIcon,
|
||||
),
|
||||
const SizedBox(width: AppDimens.cardPlayCountGap),
|
||||
Text(
|
||||
formatPlayCount(viewCount),
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardPlayCountFont,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _tags() {
|
||||
final visible = tags.take(3).toList(growable: false);
|
||||
return Text(
|
||||
|
||||
@@ -50,18 +50,28 @@ class HomeFeedCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
drama.title,
|
||||
key: Key('home-feed-title-${drama.id}'),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
color: AppColors.navSelected,
|
||||
fontSize: AppDimens.cardTitleFont,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: AppDimens.cardTitleLineHeight,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
drama.title,
|
||||
key: Key('home-feed-title-${drama.id}'),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
color: AppColors.navSelected,
|
||||
fontSize: AppDimens.cardTitleFont,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: AppDimens.cardTitleLineHeight,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppDimens.spaceXs),
|
||||
_views(),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: AppDimens.cardTitleTagGap),
|
||||
_tags(),
|
||||
@@ -102,11 +112,6 @@ class HomeFeedCard extends StatelessWidget {
|
||||
keyPrefix: '${drama.id}-${badge.name}',
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: AppDimens.spaceXs,
|
||||
bottom: AppDimens.spaceXs,
|
||||
child: _views(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -141,33 +146,27 @@ class HomeFeedCard extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _views() {
|
||||
return Container(
|
||||
return Row(
|
||||
key: Key('home-feed-views-${drama.id}'),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.playerOverlayPill,
|
||||
borderRadius: BorderRadius.circular(AppDimens.pillRadius),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.auto_awesome_rounded,
|
||||
size: AppDimens.cardViewsIcon,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.auto_awesome_rounded,
|
||||
size: AppDimens.cardViewsIcon,
|
||||
color: AppColors.navSelected,
|
||||
),
|
||||
const SizedBox(width: AppDimens.cardPlayCountGap),
|
||||
Text(
|
||||
formatPlayCount(drama.viewCount),
|
||||
style: const TextStyle(
|
||||
color: AppColors.navSelected,
|
||||
fontSize: AppDimens.cardPlayCountFont,
|
||||
fontWeight: FontWeight.w400,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
const SizedBox(width: 1),
|
||||
Text(
|
||||
formatPlayCount(drama.viewCount),
|
||||
style: const TextStyle(
|
||||
color: AppColors.navSelected,
|
||||
fontSize: AppDimens.cardViewsFont,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: 0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,37 +68,27 @@ class RecommendSectionCard extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: AppDimens.cardCoverTitleGap),
|
||||
Row(
|
||||
key: Key('recommend-views-$sectionKey-${drama.id}'),
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.auto_awesome_rounded,
|
||||
color: AppColors.textPrimary,
|
||||
size: AppDimens.cardViewsIcon,
|
||||
),
|
||||
Text(
|
||||
formatPlayCount(drama.viewCount),
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardViewsFont,
|
||||
Expanded(
|
||||
child: Text(
|
||||
drama.title,
|
||||
key: Key('recommend-title-$sectionKey-${drama.id}'),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardTitleFont,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: AppDimens.cardTitleLineHeight,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppDimens.spaceXs),
|
||||
_views(),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
drama.title,
|
||||
key: Key('recommend-title-$sectionKey-${drama.id}'),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardTitleFont,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: AppDimens.cardTitleLineHeight,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppDimens.cardTitleTagGap),
|
||||
_tags(),
|
||||
],
|
||||
@@ -107,6 +97,30 @@ class RecommendSectionCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _views() {
|
||||
return Row(
|
||||
key: Key('recommend-views-$sectionKey-${drama.id}'),
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.auto_awesome_rounded,
|
||||
color: AppColors.textPrimary,
|
||||
size: AppDimens.cardViewsIcon,
|
||||
),
|
||||
const SizedBox(width: AppDimens.cardPlayCountGap),
|
||||
Text(
|
||||
formatPlayCount(drama.viewCount),
|
||||
style: const TextStyle(
|
||||
color: AppColors.textPrimary,
|
||||
fontSize: AppDimens.cardPlayCountFont,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
List<String> _cardTags() {
|
||||
final seen = <String>{};
|
||||
return [drama.genre, drama.category]
|
||||
|
||||
@@ -87,7 +87,8 @@ void main() {
|
||||
final views = tester.widget<Text>(
|
||||
find.byKey(const Key('following-views-the-signal-demo')),
|
||||
);
|
||||
expect(views.style?.fontSize, AppDimens.cardViewsFont);
|
||||
expect(views.style?.fontSize, AppDimens.cardPlayCountFont);
|
||||
expect(views.style?.fontWeight, FontWeight.w400);
|
||||
expect(views.style?.color, AppColors.textPrimary);
|
||||
expect(
|
||||
find.descendant(
|
||||
|
||||
@@ -74,8 +74,13 @@ void main() {
|
||||
find.descendant(of: views, matching: find.byType(Text)),
|
||||
);
|
||||
expect(viewsText.data, '44.5w');
|
||||
expect(viewsText.style?.fontSize, AppDimens.cardViewsFont);
|
||||
expect(viewsText.style?.fontSize, AppDimens.cardPlayCountFont);
|
||||
expect(viewsText.style?.fontWeight, FontWeight.w400);
|
||||
expect(viewsText.style?.color, AppColors.navSelected);
|
||||
expect(
|
||||
find.descendant(of: cover, matching: find.byKey(views)),
|
||||
findsNothing,
|
||||
);
|
||||
expect(
|
||||
find.descendant(
|
||||
of: views,
|
||||
|
||||
@@ -108,7 +108,8 @@ void main() {
|
||||
matching: find.byType(Text),
|
||||
),
|
||||
);
|
||||
expect(views.style?.fontSize, AppDimens.cardViewsFont);
|
||||
expect(views.style?.fontSize, AppDimens.cardPlayCountFont);
|
||||
expect(views.style?.fontWeight, FontWeight.w400);
|
||||
expect(views.style?.color, AppColors.textPrimary);
|
||||
final viewIcon = find.descendant(
|
||||
of: find.byKey(const Key('recommend-views-hits-the-signal-demo')),
|
||||
|
||||
Reference in new issue
Block a user