diff --git a/lib/core/theme/app_dimens.dart b/lib/core/theme/app_dimens.dart index 441162e..84d6ee0 100644 --- a/lib/core/theme/app_dimens.dart +++ b/lib/core/theme/app_dimens.dart @@ -150,8 +150,8 @@ abstract final class AppDimens { static const double recommendSectionTitle = 17; static const double recommendSectionSubtitle = 11; static const double recommendSectionMore = 12; - // 封面 122*(4/3)≈163 + 间距6 + 两行标题39 + 间距6 + 标签13 ≈ 227。 - static const double recommendRowHeight = 228; + // 封面 122*(4/3)≈163 + 间距6 + 两行标题≈42 + 间距6 + 标签≈13 ≈ 230,留 6 余量。 + static const double recommendRowHeight = 236; static const double recommendCardWidth = 122; /// 首页热播榜。 @@ -189,9 +189,9 @@ abstract final class AppDimens { static const double followingAddIconStroke = 1.5; static const double followingGridGap = 6; static const double followingGridRowGap = 12; - // 单行标题 16*1.3=20.8 + 间距 6+4 + 副标题行高约 18.6 ≈ 49.4,留 0.6 余量; - // 按 48 估算在副标题行高偏高的字体下会溢出 1~2px。 - static const double followingCardTextExtent = 50; + + /// 追剧网格卡文字区:间距 6 + 两行剧名 16*1.3*2=41.6 ≈ 48,留 4 余量。 + static const double followingCardTextExtent = 52; static const double followingSubtitleFont = 12; static const double followingSubtitleGap = 4; static const double followingProgressHeight = 2; diff --git a/lib/pages/downloads/downloads_page.dart b/lib/pages/downloads/downloads_page.dart index f268916..857b829 100644 --- a/lib/pages/downloads/downloads_page.dart +++ b/lib/pages/downloads/downloads_page.dart @@ -374,7 +374,7 @@ class _LicenseTile extends StatelessWidget { Expanded( child: Text( license.dramaTitle, - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onSurface, diff --git a/lib/pages/filter/filter_page.dart b/lib/pages/filter/filter_page.dart index d1f62d0..5e2bbc2 100644 --- a/lib/pages/filter/filter_page.dart +++ b/lib/pages/filter/filter_page.dart @@ -23,7 +23,9 @@ const double _optionHorizontal = 5; const double _optionVertical = 5; const double _optionRunGap = 4; const double _cardGap = 14; -const double _gridAspectRatio = 0.56; + +/// 卡片比例:三列网格里要装下封面 + 两行剧名 + 元信息。 +const double _gridAspectRatio = 0.53; const double _groupFontSize = 13; const double _labelFontSize = 12; diff --git a/lib/pages/filter/widgets/filter_result_card.dart b/lib/pages/filter/widgets/filter_result_card.dart index d51a8a2..0cdc2df 100644 --- a/lib/pages/filter/widgets/filter_result_card.dart +++ b/lib/pages/filter/widgets/filter_result_card.dart @@ -88,7 +88,7 @@ class FilterResultCard extends StatelessWidget { Text( drama.title, key: Key('filter-title-${drama.id}'), - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onSurface, diff --git a/lib/pages/following/following_favorites_grid.dart b/lib/pages/following/following_favorites_grid.dart index 19885d8..92a712d 100644 --- a/lib/pages/following/following_favorites_grid.dart +++ b/lib/pages/following/following_favorites_grid.dart @@ -167,18 +167,10 @@ class FollowingFavoritesGrid extends StatelessWidget { bool isEditing, Set picked, ) { - final l10n = AppLocalizations.of(context)!; if (index == controller.cards.length) { return FollowingAddCard(onTap: onGoHome); } final drama = controller.cards[index]; - final record = history.recordForDrama(drama.id); - final episode = drama.episodes.isEmpty ? 1 : drama.episodes.first.number; - final watchedEpisode = record?.episodeNumber ?? 0; - final total = drama.episodeCount; - final subtitle = watchedEpisode > 0 && total > 0 - ? l10n.watchedEpisodeTotal(watchedEpisode, total) - : l10n.favoriteEpisodeProgress(episode, total); return FollowingGridCard( dramaId: drama.id, title: drama.localizedTitle(Localizations.localeOf(context).languageCode), @@ -186,10 +178,7 @@ class FollowingFavoritesGrid extends StatelessWidget { viewCount: drama.viewCount, editing: isEditing, selected: isEditing ? picked.contains(drama.id) : null, - subtitle: subtitle, - // TODO(backend): Drama 增加 hasUpdate / latestEpisodeNumber / isFinished - // 字段后,在此传 updateBadge(l10n.hasUpdateBadge)、红色更新副标题 - // (l10n.updatedToEpisode)或灰色完结副标题(l10n.finishedAllEpisodes)。 + // TODO(backend): Drama 增加 hasUpdate 字段后,在此传 updateBadge。 onTap: () => _openOrToggle(context, drama.id, isEditing), ); } diff --git a/lib/pages/following/following_grid_card.dart b/lib/pages/following/following_grid_card.dart index bdf7d85..ac360d8 100644 --- a/lib/pages/following/following_grid_card.dart +++ b/lib/pages/following/following_grid_card.dart @@ -19,21 +19,18 @@ class FollowingGridCard extends StatelessWidget { required this.title, required this.posterUrl, required this.viewCount, - required this.subtitle, required this.onTap, this.progress, this.editing = false, this.selected, this.onRemove, this.updateBadge, - this.subtitleColor, }); final String dramaId; final String title; final String posterUrl; final int viewCount; - final String subtitle; final VoidCallback onTap; final double? progress; final bool editing; @@ -44,9 +41,6 @@ class FollowingGridCard extends StatelessWidget { /// 待后端在 Drama 增加更新状态字段后由收藏网格传入。 final String? updateBadge; - /// 副标题颜色;更新中用强调红,完结用默认灰。 - final Color? subtitleColor; - @override Widget build(BuildContext context) { return InkWell( @@ -165,7 +159,7 @@ class FollowingGridCard extends StatelessWidget { const SizedBox(height: AppDimens.cardCoverTitleGap), Text( title, - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.left, style: const TextStyle( @@ -175,17 +169,6 @@ class FollowingGridCard extends StatelessWidget { height: AppDimens.cardTitleLineHeight, ), ), - const SizedBox(height: AppDimens.followingSubtitleGap), - Text( - subtitle, - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.left, - style: TextStyle( - color: subtitleColor ?? AppColors.textTertiary, - fontSize: AppDimens.followingCardSubtitleFontNew, - ), - ), ], ), ); diff --git a/lib/pages/new_releases/new_releases_page.dart b/lib/pages/new_releases/new_releases_page.dart index 021105b..85c066e 100644 --- a/lib/pages/new_releases/new_releases_page.dart +++ b/lib/pages/new_releases/new_releases_page.dart @@ -22,7 +22,9 @@ const int _moreLimit = 12; const int _filmHoles = 8; const double _cardPadding = 8; const double _cardWidth = 124; -const double _rowHeight = 204; + +/// 横向卡片行高:封面 144 + 两行剧名 + 上映日期。 +const double _rowHeight = 226; const double _cardRadius = 12; const double _loadMoreThreshold = 200; @@ -173,9 +175,7 @@ class _NewReleasesPageState extends State { child: SizedBox(height: 14), ), if (more.isNotEmpty) ...[ - SliverToBoxAdapter( - child: _moreHeader(l10n), - ), + SliverToBoxAdapter(child: _moreHeader(l10n)), const SliverToBoxAdapter( child: SizedBox(height: 10), ), @@ -467,7 +467,7 @@ class _NewReleasesPageState extends State { const SizedBox(height: 4), Text( drama.title, - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onSurface, diff --git a/lib/pages/ranking/ranking_page.dart b/lib/pages/ranking/ranking_page.dart index cae6301..898cf2a 100644 --- a/lib/pages/ranking/ranking_page.dart +++ b/lib/pages/ranking/ranking_page.dart @@ -464,7 +464,7 @@ class _RankingRow extends StatelessWidget { children: [ Text( drama.title, - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textPrimary, diff --git a/lib/pages/recommend/widgets/home_recommend_content.dart b/lib/pages/recommend/widgets/home_recommend_content.dart index d7c4b2f..cbe6933 100644 --- a/lib/pages/recommend/widgets/home_recommend_content.dart +++ b/lib/pages/recommend/widgets/home_recommend_content.dart @@ -15,6 +15,12 @@ const double _cardCoverHeight = 157; const double _cardGap = 9; const double _cardRadius = 12; +/// 海报卡封面以下的高度:上间距 8 + 两行剧名 + 2 + 集数行 + 余量。 +/// +/// 横向列表和网格都要给一个有限的卡片高度,这里是唯一来源, +/// 两行剧名撑高时只改这一处,不会出现某个入口高度不够而溢出。 +const double homePosterCardBodyExtent = 62; + /// 上新横滑卡板块。无板块标题,卡片左上角带「上新」角标。 /// 内层横向 ListView 会自行识别横向手势,不与外层纵向滚动冲突。 class HomeNewArrivalRow extends StatelessWidget { @@ -32,8 +38,7 @@ class HomeNewArrivalRow extends StatelessWidget { if (dramas.isEmpty) return const SizedBox.shrink(); return SizedBox( key: const Key('home-new-arrival-row'), - height: - _cardCoverHeight + 8 + 20 + 2 + 16, // 封面 + 剧名行 + 集数行 + 余量 + height: _cardCoverHeight + homePosterCardBodyExtent, child: ListView.separated( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: _pageSide), @@ -130,7 +135,7 @@ class HomePosterCard extends StatelessWidget { const SizedBox(height: 8), Text( drama.localizedTitle(lang), - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textPrimary, @@ -192,7 +197,11 @@ class HomeEditorPickBanner extends StatelessWidget { gradient: LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, - colors: [Color(0xE6000000), Color(0x4D000000), Color(0x1A000000)], + colors: [ + Color(0xE6000000), + Color(0x4D000000), + Color(0x1A000000), + ], ), ), ),