opt video bar

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-12 14:14:57 +08:00
parent e251eaf811
commit a94493705d
3 changed files with 232 additions and 283 deletions

View File

@@ -335,7 +335,7 @@ class PlPlayerController {
late final bool enableHA = Pref.enableHA; late final bool enableHA = Pref.enableHA;
late final String hwdec = Pref.hardwareDecoding; late final String hwdec = Pref.hardwareDecoding;
late final defaultBtmProgressBehavior = late final progressType =
BtmProgressBehavior.values[Pref.btmProgressBehavior]; BtmProgressBehavior.values[Pref.btmProgressBehavior];
late final enableQuickDouble = Pref.enableQuickDouble; late final enableQuickDouble = Pref.enableQuickDouble;
late final fullScreenGestureReverse = Pref.fullScreenGestureReverse; late final fullScreenGestureReverse = Pref.fullScreenGestureReverse;

View File

@@ -160,11 +160,16 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
} }
StreamSubscription? _listener; StreamSubscription? _listener;
StreamSubscription? _controlsListener;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
plPlayerController.getPlayerKey = () => key; plPlayerController.getPlayerKey = () => key;
_controlsListener = plPlayerController.showControls.listen((bool val) {
final visible = val && !plPlayerController.controlsLock.value;
visible ? animationController.forward() : animationController.reverse();
});
animationController = AnimationController( animationController = AnimationController(
vsync: this, vsync: this,
duration: const Duration(milliseconds: 100), duration: const Duration(milliseconds: 100),
@@ -240,6 +245,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
@override @override
void dispose() { void dispose() {
_listener?.cancel(); _listener?.cancel();
_controlsListener?.cancel();
animationController.dispose(); animationController.dispose();
FlutterVolumeController.removeListener(); FlutterVolumeController.removeListener();
transformationController.dispose(); transformationController.dispose();
@@ -659,9 +665,10 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
children: [ children: [
...userSpecifyItemLeft.map(progressWidget), ...userSpecifyItemLeft.map(progressWidget),
Expanded( Expanded(
child: FittedBox( child: LayoutBuilder(
builder: (context, constraints) => FittedBox(
child: ConstrainedBox( child: ConstrainedBox(
constraints: BoxConstraints(minWidth: maxWidth), constraints: BoxConstraints(minWidth: constraints.maxWidth),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: userSpecifyItemRight.map(progressWidget).toList(), children: userSpecifyItemRight.map(progressWidget).toList(),
@@ -669,6 +676,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
), ),
), ),
),
], ],
); );
} }
@@ -1265,24 +1273,16 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
// 头部、底部控制条 // 头部、底部控制条
Obx( Positioned.fill(
() {
final visible =
!plPlayerController.controlsLock.value &&
plPlayerController.showControls.value;
visible
? animationController.forward()
: animationController.reverse();
return Positioned.fill(
child: ClipRect( child: ClipRect(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
AppBarAni( AppBarAni(
isTop: true, isTop: true,
controller: animationController, controller: animationController,
child: widget.headerControl, child: widget.headerControl,
), ),
const Spacer(),
AppBarAni( AppBarAni(
isTop: false, isTop: false,
controller: animationController, controller: animationController,
@@ -1300,8 +1300,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
], ],
), ),
), ),
);
},
), ),
// Positioned( // Positioned(
@@ -1372,20 +1370,19 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
/// 进度条 live模式下禁用 /// 进度条 live模式下禁用
Obx( if (!plPlayerController.isLive &&
plPlayerController.progressType != BtmProgressBehavior.alwaysHide)
Positioned(
bottom: -2.2,
left: 0,
right: 0,
child: Obx(
() { () {
final int value = plPlayerController.sliderPositionSeconds.value;
final int max = plPlayerController.durationSeconds.value.inSeconds;
final int buffer = plPlayerController.bufferedSeconds.value;
if (plPlayerController.showControls.value) { if (plPlayerController.showControls.value) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
switch (plPlayerController.defaultBtmProgressBehavior) { switch (plPlayerController.progressType) {
case BtmProgressBehavior.alwaysShow:
break;
case BtmProgressBehavior.alwaysHide:
return const SizedBox.shrink();
case BtmProgressBehavior.onlyShowFullScreen: case BtmProgressBehavior.onlyShowFullScreen:
if (!isFullScreen) { if (!isFullScreen) {
return const SizedBox.shrink(); return const SizedBox.shrink();
@@ -1394,40 +1391,25 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
if (isFullScreen) { if (isFullScreen) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
default:
} }
if (plPlayerController.isLive) { return Stack(
return const SizedBox.shrink();
}
if (value > max || max <= 0) {
return const SizedBox.shrink();
}
return Positioned(
bottom: -2.2,
left: 0,
right: 0,
child: Semantics(
// label: '${(value / max * 100).round()}%',
value: '${(value / max * 100).round()}%',
// enabled: false,
child: Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
children: [ children: [
if (plPlayerController.dmTrend.isNotEmpty &&
plPlayerController.showDmTreandChart.value)
buildDmChart(theme, plPlayerController),
if (plPlayerController.viewPointList.isNotEmpty &&
plPlayerController.showVP.value)
buildViewPointWidget(
plPlayerController,
4.25,
maxWidth,
),
IgnorePointer( IgnorePointer(
child: ProgressBar( child: Obx(() {
final int value =
plPlayerController.sliderPositionSeconds.value;
final int max =
plPlayerController.durationSeconds.value.inSeconds;
final int buffer =
plPlayerController.bufferedSeconds.value;
if (value > max || max <= 0) {
return const SizedBox.shrink();
}
return ProgressBar(
progress: Duration(seconds: value), progress: Duration(seconds: value),
buffered: Duration(seconds: buffer), buffered: Duration(seconds: buffer),
total: Duration(seconds: max), total: Duration(seconds: max),
@@ -1438,33 +1420,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
thumbColor: primary, thumbColor: primary,
barHeight: 3.5, barHeight: 3.5,
thumbRadius: draggingFixedProgressBar.value ? 7 : 2.5, thumbRadius: draggingFixedProgressBar.value ? 7 : 2.5,
// onDragStart: (duration) { );
// feedBack(); }),
// plPlayerController.onChangedSliderStart();
// },
// onDragUpdate: (duration) {
// plPlayerController
// .onUpdatedSliderProgress(duration.timeStamp);
// if (plPlayerController.showSeekPreview) {
// if (plPlayerController.showPreview.value.not) {
// plPlayerController.showPreview.value = true;
// }
// plPlayerController.previewDx.value =
// duration.localPosition.dx;
// }
// },
// onSeek: (duration) {
// if (plPlayerController.showSeekPreview) {
// plPlayerController.showPreview.value = false;
// }
// plPlayerController.onChangedSliderEnd();
// plPlayerController
// .onChangedSlider(duration.inSeconds.toDouble());
// plPlayerController.seekTo(
// Duration(seconds: duration.inSeconds),
// type: 'slider');
// },
),
), ),
if (plPlayerController.segmentList.isNotEmpty) if (plPlayerController.segmentList.isNotEmpty)
Positioned( Positioned(
@@ -1484,7 +1441,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
), ),
if (plPlayerController.viewPointList.isNotEmpty && if (plPlayerController.viewPointList.isNotEmpty &&
plPlayerController.showVP.value) plPlayerController.showVP.value) ...[
Positioned( Positioned(
left: 0, left: 0,
right: 0, right: 0,
@@ -1501,6 +1458,15 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
), ),
), ),
buildViewPointWidget(
plPlayerController,
4.25,
maxWidth,
),
],
if (plPlayerController.dmTrend.isNotEmpty &&
plPlayerController.showDmTreandChart.value)
buildDmChart(theme, plPlayerController),
if (plPlayerController.showSeekPreview) if (plPlayerController.showSeekPreview)
Positioned( Positioned(
left: 0, left: 0,
@@ -1512,20 +1478,10 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
), ),
], ],
),
// SlideTransition(
// position: Tween<Offset>(
// begin: Offset.zero,
// end: const Offset(0, -1),
// ).animate(CurvedAnimation(
// parent: animationController,
// curve: Curves.easeInOut,
// )),
// child: ),
),
); );
}, },
), ),
),
// 锁 // 锁
SafeArea( SafeArea(

View File

@@ -27,44 +27,30 @@ class BottomControl extends StatelessWidget {
Timer? accessibilityDebounce; Timer? accessibilityDebounce;
double lastAnnouncedValue = -1; double lastAnnouncedValue = -1;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10), padding: const EdgeInsets.fromLTRB(10, 0, 10, 12),
child: LayoutBuilder( child: LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
final maxWidth = constraints.maxWidth; final maxWidth = constraints.maxWidth;
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Obx( Padding(
() { padding: const EdgeInsets.fromLTRB(10, 0, 10, 7),
final int value = controller.sliderPositionSeconds.value; child: Obx(
final int max = controller.durationSeconds.value.inSeconds; () => Stack(
clipBehavior: Clip.none,
alignment: Alignment.bottomCenter,
children: [
Obx(() {
final int value =
controller.sliderPositionSeconds.value;
final int max =
controller.durationSeconds.value.inSeconds;
final int buffer = controller.bufferedSeconds.value; final int buffer = controller.bufferedSeconds.value;
if (value > max || max <= 0) { if (value > max || max <= 0) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
return Padding( return ProgressBar(
padding: const EdgeInsets.only(
left: 10,
right: 10,
bottom: 7,
),
child: Semantics(
value: '${(value / max * 100).round()}%',
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.bottomCenter,
children: [
if (controller.dmTrend.isNotEmpty &&
controller.showDmTreandChart.value)
buildDmChart(theme, controller, 4.5),
if (controller.viewPointList.isNotEmpty &&
controller.showVP.value)
buildViewPointWidget(
controller,
8.75,
maxWidth - 20,
),
ProgressBar(
progress: Duration(seconds: value), progress: Duration(seconds: value),
buffered: Duration(seconds: buffer), buffered: Duration(seconds: buffer),
total: Duration(seconds: max), total: Duration(seconds: max),
@@ -125,7 +111,8 @@ class BottomControl extends StatelessWidget {
TextDirection.ltr, TextDirection.ltr,
); );
}, },
), );
}),
if (controller.segmentList.isNotEmpty) if (controller.segmentList.isNotEmpty)
Positioned( Positioned(
left: 0, left: 0,
@@ -144,7 +131,7 @@ class BottomControl extends StatelessWidget {
), ),
), ),
if (controller.viewPointList.isNotEmpty && if (controller.viewPointList.isNotEmpty &&
controller.showVP.value) controller.showVP.value) ...[
Positioned( Positioned(
left: 0, left: 0,
right: 0, right: 0,
@@ -161,6 +148,15 @@ class BottomControl extends StatelessWidget {
), ),
), ),
), ),
buildViewPointWidget(
controller,
8.75,
maxWidth - 20,
),
],
if (controller.dmTrend.isNotEmpty &&
controller.showDmTreandChart.value)
buildDmChart(theme, controller, 4.5),
if (controller.showSeekPreview && if (controller.showSeekPreview &&
controller.showControls.value) controller.showControls.value)
Positioned( Positioned(
@@ -175,11 +171,8 @@ class BottomControl extends StatelessWidget {
], ],
), ),
), ),
);
},
), ),
buildBottomControl(maxWidth), buildBottomControl(maxWidth),
const SizedBox(height: 12),
], ],
); );
}, },