feat(flutter): 播放页长按手势与加速态
This commit is contained in:
1 parent
7bb2714941
commit
96074bc5e8
11 files changed
+231
-4
No files matched your search
@@ -16,6 +16,8 @@ const double _topButtonSize = 36;
|
||||
const double _topBarHeight = 58;
|
||||
const double _railButtonSize = 34;
|
||||
const double _railGap = 18;
|
||||
const double _boostHintIconSize = 16;
|
||||
const double _boostHintFontSize = 13;
|
||||
const List<Shadow> _playerTextShadows = [
|
||||
Shadow(color: Colors.black54, blurRadius: 5, offset: Offset(0, 1)),
|
||||
];
|
||||
@@ -45,10 +47,16 @@ class PlayerPlaybackOverlay extends StatelessWidget {
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
key: const Key('player-video-tap'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: actions.onTogglePlay,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => GestureDetector(
|
||||
key: const Key('player-video-tap'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: actions.onTogglePlay,
|
||||
onLongPressStart: (details) =>
|
||||
_handleLongPressStart(details, constraints.maxWidth),
|
||||
onLongPressEnd: (_) => actions.onBoostEnd(),
|
||||
onLongPressCancel: actions.onBoostEnd,
|
||||
),
|
||||
),
|
||||
),
|
||||
_top(context),
|
||||
@@ -120,6 +128,17 @@ class PlayerPlaybackOverlay extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// 长按分区:中间 1/3 弹更多,左右各 1/3 开始加速。
|
||||
void _handleLongPressStart(LongPressStartDetails details, double width) {
|
||||
final third = width / 3;
|
||||
final dx = details.localPosition.dx;
|
||||
if (dx < third || dx > width - third) {
|
||||
actions.onBoostStart();
|
||||
return;
|
||||
}
|
||||
actions.onLongPressCenter();
|
||||
}
|
||||
|
||||
Widget _rail(BuildContext context) {
|
||||
final compact = MediaQuery.sizeOf(context).height < 700;
|
||||
return Positioned(
|
||||
@@ -149,6 +168,7 @@ class PlayerPlaybackOverlay extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (controlsVisible) _bottomInfo(context),
|
||||
if (data.boosting) _boostHint(),
|
||||
_bottomProgress(),
|
||||
_bottomActions(),
|
||||
],
|
||||
@@ -156,6 +176,35 @@ class PlayerPlaybackOverlay extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// 加速提示:橙色小三角 + 当前倍速文案,悬在进度条上方。
|
||||
Widget _boostHint() {
|
||||
return Padding(
|
||||
key: const Key('player-speed-boost-hint'),
|
||||
padding: const EdgeInsets.only(bottom: 6),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.play_arrow_rounded,
|
||||
color: AppColors.blue,
|
||||
size: _boostHintIconSize,
|
||||
shadows: _playerTextShadows,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
data.l10n.speedBoosting(data.playbackSpeed.toStringAsFixed(1)),
|
||||
style: const TextStyle(
|
||||
color: AppColors.blue,
|
||||
fontSize: _boostHintFontSize,
|
||||
fontWeight: FontWeight.w700,
|
||||
shadows: _playerTextShadows,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _bottomInfo(BuildContext context) {
|
||||
final series = localizedDramaTitle(data.l10n, data.drama);
|
||||
final synopsis = localizedDramaSynopsis(data.l10n, data.drama);
|
||||
|
||||
@@ -22,6 +22,7 @@ class PlayerOverlayData {
|
||||
required this.playing,
|
||||
required this.playbackSpeed,
|
||||
required this.totalEpisodes,
|
||||
required this.boosting,
|
||||
this.authorNote = '',
|
||||
});
|
||||
|
||||
@@ -61,6 +62,9 @@ class PlayerOverlayData {
|
||||
/// 可见集数量。
|
||||
final int totalEpisodes;
|
||||
|
||||
/// 是否处于长按加速态。
|
||||
final bool boosting;
|
||||
|
||||
/// 作者声明;没有后端字段时为空。
|
||||
final String authorNote;
|
||||
}
|
||||
@@ -83,6 +87,9 @@ class PlayerOverlayActions {
|
||||
required this.onMore,
|
||||
required this.onScrubStart,
|
||||
required this.onSeek,
|
||||
required this.onLongPressCenter,
|
||||
required this.onBoostStart,
|
||||
required this.onBoostEnd,
|
||||
});
|
||||
|
||||
/// 返回上一页。
|
||||
@@ -126,4 +133,13 @@ class PlayerOverlayActions {
|
||||
|
||||
/// 提交进度跳转。
|
||||
final Future<void> Function(Duration)? onSeek;
|
||||
|
||||
/// 长按画面中间:弹出更多面板。
|
||||
final VoidCallback onLongPressCenter;
|
||||
|
||||
/// 长按画面两侧:开始加速。
|
||||
final VoidCallback onBoostStart;
|
||||
|
||||
/// 长按结束或取消:结束加速。
|
||||
final VoidCallback onBoostEnd;
|
||||
}
|
||||
Reference in new issue
Block a user