style(player): 播放页与首页浮层的控件样式统一

播放页顶部按钮与选集条去掉底色、进度条不再画滑块圆点并压到最底部;
剧名与简介收在互动栏左侧,清屏后只留右下角退出按钮。
首页观看条与进度条共用 20pt 页边距,进度槽底色与播放页一致。
This commit is contained in:
Vicky authored and trae-solo-agent committed 2026-10-29 15:44:22 +08:00
1 parent d5bcda54d3
commit 543d0aadd5
12 files changed
+298 -297

No files matched your search

@@ -4,6 +4,10 @@ import 'package:flutter/material.dart';
import '../../../core/theme/app_colors.dart';
const List<Shadow> _iconShadows = [
Shadow(color: AppColors.shadow, blurRadius: 6, offset: Offset(0, 1)),
];
/// Shared floating action used to leave clear-screen mode.
class ExitClearScreenButton extends StatelessWidget {
const ExitClearScreenButton({
@@ -25,11 +29,15 @@ class ExitClearScreenButton extends StatelessWidget {
onPressed: onPressed,
padding: EdgeInsets.zero,
style: IconButton.styleFrom(
backgroundColor: AppColors.controlScrim,
backgroundColor: AppColors.transparent,
foregroundColor: AppColors.onPrimary,
shape: const CircleBorder(),
),
icon: const Icon(Icons.fullscreen_exit_rounded, size: 18),
icon: const Icon(
Icons.fullscreen_exit_rounded,
size: 22,
shadows: _iconShadows,
),
),
);
}
+30 -27
View File
@@ -21,13 +21,16 @@ import 'scrub_preview_card.dart';
part 'home_feed_overlay_parts.dart';
const double _progressHeight = 2;
const double _progressHitHeight = 32;
/// 进度条触控带高度:没有滑块圆点后收到 16pt,够手指按住这条线拖动。
const double _progressHitHeight = 16;
const double _pageHorizontal = 20;
const double _railRight = 14;
const double _railGap = 12;
// 观看条高 44;2pt 进度线视觉上沿距观看条顶约 7pt(线中心距进度条盒底 8)。
// 信息面板底边取 44+16=60,使简介↔进度线、进度线↔观看条两侧间距均为 7pt。
const double _bottomInfoInset = homeFeedWatchAllHeight + 16;
// 进度线贴着屏幕底部(线心距底 4pt),观看条底边只留 8pt,视觉上就是线上一根条。
const double _watchAllBottomInset = 8;
// 信息面板底边直接贴住观看条顶沿,中间不留缝。
const double _bottomInfoInset = _watchAllBottomInset + homeFeedWatchAllHeight;
const double _railBottomOffset = 40;
const Duration _overlayFadeDuration = Duration(milliseconds: 120);
const List<Shadow> _boostTextShadows = [
@@ -152,7 +155,7 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
Positioned(
left: 0,
right: 0,
bottom: homeFeedWatchAllHeight + 12,
bottom: _watchAllBottomInset + homeFeedWatchAllHeight + 12,
child: AnimatedOpacity(
duration: _overlayFadeDuration,
opacity: widget.boosting ? 1 : 0,
@@ -162,10 +165,30 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
),
),
),
// 观看条在下、进度条在上:进度条 32pt 触控盒要盖住观看条下沿的空白,
// 否则拖拽 seek 的起点会被观看条吞掉。两块的可见区域(文字/进度线)互不遮挡。
Positioned(
left: _pageHorizontal,
right: _pageHorizontal,
bottom: homeFeedWatchAllHeight,
bottom: _watchAllBottomInset,
child: AnimatedOpacity(
duration: _overlayFadeDuration,
opacity: widget.visible && !_scrubbing && !widget.boosting
? 1
: 0,
child: IgnorePointer(
ignoring: !widget.visible || _scrubbing || widget.boosting,
child: HomeFeedWatchAllBar(
drama: widget.drama,
onTap: widget.onOpenFullPlayer,
),
),
),
),
Positioned(
left: _pageHorizontal,
right: _pageHorizontal,
bottom: 0,
child: _FeedProgressBar(
controller: widget.controller,
locked: widget.locked,
@@ -182,27 +205,7 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
onSeek: widget.onSeek,
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: AnimatedOpacity(
duration: _overlayFadeDuration,
opacity: widget.visible && !_scrubbing && !widget.boosting
? 1
: 0,
child: IgnorePointer(
ignoring: !widget.visible || _scrubbing || widget.boosting,
child: HomeFeedWatchAllBar(
drama: widget.drama,
onTap: widget.onOpenFullPlayer,
),
),
),
),
// 信息面板放在最后(最上层):进度条 32px 触控盒向上伸进底部避让区,
// 若面板在前,简介/展开按钮底部的触控留白会被进度条吞掉点击。
// 视觉上避让条带为空,提层不改变观感。
// 信息面板放在最后(最上层),底部避让区永远优先响应简介/展开按钮的点击。
Positioned(
left: _pageHorizontal,
right: _railRight,
@@ -2,10 +2,9 @@
part of 'home_feed_overlay.dart';
const double _thumbSize = 6;
const double _thumbActiveSize = 14;
const double _trackActiveHeight = 6;
const double _lineCenterFromBottom = 8;
// 进度线贴住屏幕底部(线心距底 4pt);播放进度只靠蓝色已播段表达,不画滑块圆点。
const double _lineCenterFromBottom = 4;
const double _timeBubbleWidth = 96;
const double _timeBubbleMargin = 12;
const Key _inactiveTrackKey = Key('home-feed-progress-inactive');
@@ -305,7 +304,7 @@ class _FeedProgressBarState extends State<_FeedProgressBar> {
height: widget.height,
child: ColoredBox(
key: _inactiveTrackKey,
color: AppColors.border,
color: AppColors.inactiveTrack,
),
),
),
@@ -345,20 +344,11 @@ class _FeedProgressBarState extends State<_FeedProgressBar> {
Widget _track(double fraction, double width) {
final dragging = _preview != null;
final trackHeight = dragging ? _trackActiveHeight : widget.height;
final size = dragging ? _thumbActiveSize : _thumbSize;
final finger = (width * fraction).clamp(0.0, width).toDouble();
final thumbSlotLeft = dragging
? finger - _thumbActiveSize / 2
: (finger - _thumbActiveSize / 2)
.clamp(0.0, width - _thumbActiveSize)
.toDouble();
final playedWidth = dragging ? finger : width * fraction;
final playedWidth = (width * fraction).clamp(0.0, width).toDouble();
final trackSlotBottom = _lineCenterFromBottom - _trackActiveHeight / 2;
final thumbSlotBottom = _lineCenterFromBottom - _thumbActiveSize / 2;
return SizedBox(
height: widget.hitHeight,
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned(
left: 0,
@@ -374,7 +364,8 @@ class _FeedProgressBarState extends State<_FeedProgressBar> {
key: const Key('home-feed-progress-track'),
width: width,
height: trackHeight,
color: AppColors.border,
// 和剧集播放页进度条共用同一个槽底色,两个入口观感一致。
color: AppColors.inactiveTrack,
),
),
Align(
@@ -390,24 +381,6 @@ class _FeedProgressBarState extends State<_FeedProgressBar> {
),
),
),
Positioned(
left: thumbSlotLeft,
bottom: thumbSlotBottom,
child: SizedBox.square(
dimension: _thumbActiveSize,
child: Center(
child: Container(
key: const Key('home-feed-progress-thumb'),
width: size,
height: size,
decoration: const BoxDecoration(
color: AppColors.onPrimary,
shape: BoxShape.circle,
),
),
),
),
),
],
),
);
@@ -13,7 +13,14 @@ import 'interaction_rail.dart';
const double _seriesFont = 17;
const double _tagFont = 12;
const double _synopsisFont = 14;
const double _watchAllHeight = 44;
const double _watchAllHeight = 38;
/// 观看条内部左右留白与圆角:外沿由 overlay 按页面边距对齐,内部不再重复内缩。
const double _watchAllInset = 12;
const double _watchAllRadius = 12;
/// 标题、标签、简介之间的行间距:底部信息本来就挤,留 4pt 够分层。
const double _blockGap = 4;
const List<Shadow> _textShadows = [
Shadow(color: AppColors.shadow, blurRadius: 6, offset: Offset(0, 1)),
];
@@ -57,6 +64,7 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
final dramaTitle = localizedDramaTitle(l10n, widget.drama);
final synopsis = localizedDramaSynopsis(l10n, widget.drama).trim();
final genres = _genreValues(Localizations.localeOf(context).languageCode);
final tags = _tagChips(l10n, genres);
return Column(
key: const Key('home-feed-info-panel'),
mainAxisSize: MainAxisSize.min,
@@ -104,18 +112,21 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
],
),
),
const SizedBox(height: 6),
_tagMetaRow(l10n, genres),
// 没有标签就整行跳过,不给标题和简介之间留空档。
if (tags.isNotEmpty) ...[
const SizedBox(height: _blockGap),
_tagRow(tags),
],
if (synopsis.isNotEmpty) ...[
const SizedBox(height: 8),
const SizedBox(height: _blockGap),
_synopsis(l10n, synopsis),
],
],
);
}
Widget _tagMetaRow(AppLocalizations l10n, List<String> genres) {
final chips = <Widget>[
List<Widget> _tagChips(AppLocalizations l10n, List<String> genres) {
return [
if (isHotDrama(widget.drama))
_TagChip(
key: const Key('home-feed-hot-badge'),
@@ -125,6 +136,9 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
for (final genre in genres)
_TagChip(key: Key('home-feed-tag-$genre'), label: genre),
];
}
Widget _tagRow(List<Widget> chips) {
return SizedBox(
key: const Key('home-feed-tags'),
height: 22,
@@ -149,10 +163,7 @@ class _HomeFeedInfoPanelState extends State<HomeFeedInfoPanel> {
);
final span = TextSpan(
children: [
TextSpan(
text: prefix,
style: baseStyle,
),
TextSpan(text: prefix, style: baseStyle),
TextSpan(
text: ' | ',
style: baseStyle.copyWith(
@@ -368,7 +379,7 @@ class _TagChip extends StatelessWidget {
}
}
/// 底部通栏条:🎬 观看完整剧集 全 N 集。
/// 底部「观看完整剧集」条:浮在底部,不再铺满整屏宽度。
class HomeFeedWatchAllBar extends StatelessWidget {
const HomeFeedWatchAllBar({
super.key,
@@ -382,42 +393,45 @@ class HomeFeedWatchAllBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Material(
key: const Key('home-feed-full-series-bg'),
color: AppColors.textPrimary.withValues(alpha: 0.15),
child: InkWell(
key: const Key('home-feed-full-series'),
onTap: onTap,
child: SizedBox(
height: _watchAllHeight,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
children: [
const Icon(
Icons.movie_rounded,
size: 22,
color: AppColors.onPrimary,
),
const SizedBox(width: 10),
Expanded(
child: Text(
l10n.watchFullSeries('${drama.episodeCount}'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.textPrimary,
fontSize: 15,
fontWeight: FontWeight.w500,
return ClipRRect(
borderRadius: BorderRadius.circular(_watchAllRadius),
child: Material(
key: const Key('home-feed-full-series-bg'),
color: AppColors.textPrimary.withValues(alpha: 0.15),
child: InkWell(
key: const Key('home-feed-full-series'),
onTap: onTap,
child: SizedBox(
height: _watchAllHeight,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: _watchAllInset),
child: Row(
children: [
const Icon(
Icons.movie_rounded,
size: 22,
color: AppColors.onPrimary,
),
const SizedBox(width: 10),
Expanded(
child: Text(
l10n.watchFullSeries('${drama.episodeCount}'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.textPrimary,
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
),
),
const Icon(
Icons.chevron_right_rounded,
size: 22,
color: AppColors.textPrimary,
),
],
const Icon(
Icons.chevron_right_rounded,
size: 22,
color: AppColors.textPrimary,
),
],
),
),
),
),
@@ -6,7 +6,9 @@ import '../../../core/theme/app_colors.dart';
const double _toggleSize = 68;
const double _iconSize = 36;
const Color _toggleBackground = AppColors.controlSoftScrim;
/// 播放/暂停压在画面上,垫一层半透明深色圆底保证亮画面下也能看见。
const Color _toggleBackground = Color(0x66000000);
const List<Shadow> _iconShadows = [
Shadow(color: AppColors.shadow, blurRadius: 12),
];
+82 -59
View File
@@ -19,8 +19,17 @@ import 'seek_progress_bar.dart';
part 'player_overlay_parts.dart';
const double _topButtonSize = 36;
const double _topButtonSize = 40;
const double _topBarHeight = 58;
/// 底部信息、选集条、进度条之间的统一行距。
const double _blockGap = 8;
/// 底部选集条与右侧清屏按钮的统一高度,两者必须等高。
const double _bottomActionHeight = 34;
/// 选集条内部左右留白。
const double _bottomActionInset = 10;
const double _boostHintIconSize = 16;
const double _boostHintFontSize = 13;
const double _synopsisRailInset = 54;
@@ -107,11 +116,12 @@ class PlayerPlaybackOverlay extends StatelessWidget {
key: const Key('player-back'),
tooltip: data.l10n.backToSeries,
icon: Icons.chevron_left_rounded,
iconSize: 30,
onPressed: actions.onBack!,
)
else
const SizedBox(width: _topButtonSize),
const SizedBox(width: 8),
const SizedBox(width: 2),
Expanded(
child: Text(
data.l10n.episodeLabel(data.episode.number),
@@ -135,7 +145,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
_TopButton(
key: const Key('player-more'),
tooltip: data.l10n.more,
icon: Icons.more_vert_rounded,
icon: Icons.more_horiz_rounded,
onPressed: actions.onMore,
),
],
@@ -226,19 +236,20 @@ class PlayerPlaybackOverlay extends StatelessWidget {
child: _bottomInfo(context),
),
if (data.boosting) _boostHint(),
_bottomProgress(),
// 加速时收起底栏。拖动进度时底栏只隐藏,占位保留,进度条不挪位。
// 加速时收起选集条。拖动进度时只隐藏,占位保留,底部不跳动。
scrubbing
? IgnorePointer(
child: Opacity(opacity: 0, child: _bottomActions()),
)
: Offstage(offstage: data.boosting, child: _bottomActions()),
// 进度条压在最底部,和首页 feed 一致。
_bottomProgress(),
],
),
);
}
/// 加速提示:橙色小三角 + 当前倍速文案,悬在进度条上方。
/// 加速提示:橙色小三角 + 当前倍速文案,压在底部信息区下方。
Widget _boostHint() {
return Padding(
key: const Key('player-speed-boost-hint'),
@@ -270,25 +281,28 @@ class PlayerPlaybackOverlay extends StatelessWidget {
Widget _bottomInfo(BuildContext context) {
final series = localizedDramaTitle(data.l10n, data.drama);
final synopsis = localizedDramaSynopsis(data.l10n, data.drama);
// 右侧让出互动栏的宽度:剧名和简介一样,收在互动栏左侧,长标题也不会钻到按钮下面。
return Padding(
key: const Key('player-controls-bottom'),
padding: const EdgeInsets.fromLTRB(14, 8, 14, 0),
padding: const EdgeInsets.fromLTRB(
14,
_blockGap,
14 + _synopsisRailInset,
0,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_detailRow(series),
const SizedBox(height: 4),
Padding(
padding: const EdgeInsets.only(right: _synopsisRailInset),
child: _EpisodeSynopsis(
key: const Key('player-episode-synopsis'),
l10n: data.l10n,
drama: data.drama,
episodeNumber: data.episode.number,
synopsis: synopsis,
authorNote: data.authorNote,
),
_EpisodeSynopsis(
key: const Key('player-episode-synopsis'),
l10n: data.l10n,
drama: data.drama,
episodeNumber: data.episode.number,
synopsis: synopsis,
authorNote: data.authorNote,
),
],
),
@@ -296,9 +310,10 @@ class PlayerPlaybackOverlay extends StatelessWidget {
}
Widget _bottomProgress() {
// 进度条不贴底:底部留 16pt,线心离底边更远,也不再和选集条挤在一起。
return Padding(
key: const Key('player-progress-container'),
padding: EdgeInsets.fromLTRB(14, controlsVisible ? 2 : 8, 14, 0),
padding: const EdgeInsets.fromLTRB(14, 2, 14, 16),
child: SeekProgressBar(
key: const Key('player-progress'),
valueListenable: data.controller,
@@ -345,10 +360,9 @@ class PlayerPlaybackOverlay extends StatelessWidget {
),
),
),
const SizedBox(width: 4),
const Icon(
Icons.chevron_right_rounded,
color: AppColors.playerMuted,
color: AppColors.onPrimary,
size: 20,
shadows: _playerTextShadows,
),
@@ -362,55 +376,63 @@ class PlayerPlaybackOverlay extends StatelessWidget {
Widget _bottomActions() {
return Padding(
key: const Key('player-bottom-actions'),
padding: const EdgeInsets.fromLTRB(14, 6, 14, 6),
padding: const EdgeInsets.fromLTRB(14, 2, 14, 0),
child: Row(
children: [
Expanded(
child: Material(
key: const Key('player-episodes-pill'),
color: AppColors.playerOverlayPill,
borderRadius: BorderRadius.circular(7),
clipBehavior: Clip.antiAlias,
child: InkWell(
key: const Key('player-episodes'),
onTap: actions.onEpisodes,
borderRadius: BorderRadius.circular(7),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 14,
vertical: 8,
),
child: Row(
children: [
Expanded(
child: Text(
'${data.l10n.episodes} · '
'${data.l10n.allEpisodesBadge(data.totalEpisodes)} · '
'${data.l10n.freeWatch}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
// 清屏后只留右下角的退出按钮,左侧选集条一起收起。
if (!controlsVisible)
const Spacer()
else ...[
Expanded(
// 选集条给一层浅底色:视频画面亮时纯文字不好认,也顺带标出可点区域。
child: Material(
key: const Key('player-episodes-pill'),
color: AppColors.textPrimary.withValues(alpha: 0.14),
borderRadius: BorderRadius.circular(8),
clipBehavior: Clip.antiAlias,
child: InkWell(
key: const Key('player-episodes'),
onTap: actions.onEpisodes,
borderRadius: BorderRadius.circular(8),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: _bottomActionInset,
),
child: SizedBox(
height: _bottomActionHeight,
child: Row(
children: [
Expanded(
child: Text(
'${data.l10n.episodes} · '
'${data.l10n.allEpisodesBadge(data.totalEpisodes)} · '
'${data.l10n.freeWatch}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.onPrimary,
fontSize: 13.5,
fontWeight: FontWeight.w800,
shadows: _playerTextShadows,
),
),
),
const SizedBox(width: 8),
const Icon(
Icons.keyboard_arrow_up_rounded,
color: AppColors.onPrimary,
fontSize: 13.5,
fontWeight: FontWeight.w800,
size: 18,
shadows: _playerTextShadows,
),
),
],
),
const SizedBox(width: 8),
const Icon(
Icons.keyboard_arrow_up_rounded,
color: AppColors.onPrimary,
size: 18,
shadows: _playerTextShadows,
),
],
),
),
),
),
),
),
const SizedBox(width: 8),
const SizedBox(width: 8),
],
_BottomIconButton(
key: const Key('player-bottom-clear-screen'),
tooltip: controlsVisible
@@ -419,6 +441,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
icon: controlsVisible
? Icons.fullscreen_rounded
: Icons.fullscreen_exit_rounded,
height: _bottomActionHeight,
onPressed: controlsVisible ? actions.onClear : actions.onExitClear,
),
],
@@ -2,17 +2,20 @@
part of 'player_overlay.dart';
/// 顶部按钮:直接压在画面上,不加底色,靠文字/图标阴影保证可读性。
class _TopButton extends StatelessWidget {
const _TopButton({
super.key,
required this.tooltip,
required this.icon,
required this.onPressed,
this.iconSize = 22,
});
final String tooltip;
final IconData icon;
final VoidCallback onPressed;
final double iconSize;
@override
Widget build(BuildContext context) {
@@ -22,11 +25,11 @@ class _TopButton extends StatelessWidget {
tooltip: tooltip,
padding: EdgeInsets.zero,
style: IconButton.styleFrom(
backgroundColor: AppColors.controlScrim,
backgroundColor: AppColors.transparent,
foregroundColor: AppColors.onPrimary,
),
onPressed: onPressed,
icon: Icon(icon, size: 18),
icon: Icon(icon, size: iconSize, shadows: _playerTextShadows),
),
);
}
@@ -41,7 +44,7 @@ class _SpeedEntry extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Material(
color: AppColors.controlScrim,
color: AppColors.transparent,
borderRadius: BorderRadius.circular(999),
child: InkWell(
onTap: onTap,
@@ -81,25 +84,30 @@ class _BottomIconButton extends StatelessWidget {
required this.tooltip,
required this.icon,
required this.onPressed,
this.height = 40,
});
final String tooltip;
final IconData icon;
final VoidCallback onPressed;
/// 与左侧选集条等高,两个控件底部齐平。
final double height;
@override
Widget build(BuildContext context) {
return SizedBox.square(
dimension: 40,
return SizedBox(
width: 40,
height: height,
child: IconButton(
tooltip: tooltip,
padding: EdgeInsets.zero,
style: IconButton.styleFrom(
backgroundColor: AppColors.playerOverlayPill,
backgroundColor: AppColors.transparent,
foregroundColor: AppColors.onPrimary,
),
onPressed: onPressed,
icon: Icon(icon, size: 22),
icon: Icon(icon, size: 24, shadows: _playerTextShadows),
),
);
}
@@ -242,8 +250,10 @@ class _EpisodeSynopsisState extends State<_EpisodeSynopsis> {
),
),
const SizedBox(width: 2),
_toggle(widget.l10n.expandSynopsis,
padding: const EdgeInsets.only(left: 6)),
_toggle(
widget.l10n.expandSynopsis,
padding: const EdgeInsets.only(left: 6),
),
],
),
);
@@ -291,12 +301,12 @@ class _EpisodeSynopsisState extends State<_EpisodeSynopsis> {
/// 分隔竖线:同字号 w400 + 45% 透明白,靠两侧空格留白。
/// 必须用 TextSpan:WidgetSpan 占位盒的基线对齐会让第n集与简介错位。
TextSpan _separatorSpan() => TextSpan(
text: ' | ',
style: _lineStyle.copyWith(
color: AppColors.onPrimary.withValues(alpha: 0.45),
fontWeight: FontWeight.w400,
),
);
text: ' | ',
style: _lineStyle.copyWith(
color: AppColors.onPrimary.withValues(alpha: 0.45),
fontWeight: FontWeight.w400,
),
);
Widget _toggle(String label, {required EdgeInsets padding}) {
return GestureDetector(
@@ -321,10 +321,8 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
trackHeight: trackHeight,
activeTrackColor: AppColors.blue,
inactiveTrackColor: widget.inactiveTrackColor,
thumbColor: AppColors.onPrimary,
thumbShape: RoundSliderThumbShape(
enabledThumbRadius: scrubbing ? 8 : 6,
),
// 播放页进度条不画滑块圆点:进度只靠蓝色已播段表达。
thumbShape: SliderComponentShape.noThumb,
overlayShape: RoundSliderOverlayShape(
overlayRadius: widget.compact ? 12 : 18,
),