feat: drag subtitle

Closes #588

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-04-03 20:04:56 +08:00
parent 6a7d14a3f8
commit 09c8a41c52
6 changed files with 146 additions and 140 deletions

View File

@@ -949,6 +949,132 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
},
flipX: plPlayerController.flipX.value,
flipY: plPlayerController.flipY.value,
onVerticalDragStart: (details) {
if (plPlayerController.controlsLock.value) return;
if (details.localPosition.dy < 40) return;
if (details.localPosition.dx < 40) return;
if (details.localPosition.dx > context.width - 40) return;
if (details.localPosition.dy > context.height - 40) return;
_initialFocalPoint = details.localPosition;
_gestureType = null;
},
onVerticalDragUpdate: (details) {
if (plPlayerController.controlsLock.value) return;
if (plPlayerController.enableSlideVolumeBrightness.not &&
plPlayerController.enableSlideFS.not) {
return;
}
RenderBox renderBox =
_playerKey.currentContext!.findRenderObject() as RenderBox;
final double totalWidth = renderBox.size.width;
final double tapPosition = details.localPosition.dx;
final double sectionWidth = totalWidth / 3;
late String gestureType;
if (tapPosition < sectionWidth) {
if (plPlayerController.enableSlideVolumeBrightness.not) {
return;
}
// 左边区域
gestureType = 'left';
} else if (tapPosition < sectionWidth * 2) {
if (plPlayerController.enableSlideFS.not) {
return;
}
// 全屏
gestureType = 'center';
} else {
if (plPlayerController.enableSlideVolumeBrightness.not) {
return;
}
// 右边区域
gestureType = 'right';
}
if (_gestureType != null && _gestureType != gestureType) {
return;
}
_gestureType = gestureType;
if (_gestureType == 'left') {
// 左边区域 👈
final double level = renderBox.size.height * 3;
final double brightness =
_brightnessValue.value - details.delta.dy / level;
final double result = brightness.clamp(0.0, 1.0);
setBrightness(result);
} else if (_gestureType == 'center') {
// 全屏
const double threshold = 2.5; // 滑动阈值
double cumulativeDy =
details.localPosition.dy - _initialFocalPoint.dy;
void fullScreenTrigger(bool status) {
plPlayerController.triggerFullScreen(status: status);
}
if (cumulativeDy > threshold) {
_gestureType = 'center_down';
if (isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(fullScreenGestureReverse);
}
// debugPrint('center_down:$cumulativeDy');
} else if (cumulativeDy < -threshold) {
_gestureType = 'center_up';
if (!isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(!fullScreenGestureReverse);
}
// debugPrint('center_up:$cumulativeDy');
}
} else if (_gestureType == 'right') {
// 右边区域
final double level = renderBox.size.height * 0.5;
EasyThrottle.throttle(
'setVolume', const Duration(milliseconds: 20), () {
final double volume =
_volumeValue.value - details.delta.dy / level;
final double result = volume.clamp(0.0, 1.0);
setVolume(result);
});
}
},
onVerticalDragEnd: (details) {
interacting = false;
_initialFocalPoint = Offset.zero;
_gestureType = null;
},
onTap: () {
plPlayerController.controls =
!plPlayerController.showControls.value;
},
onDoubleTapDown: (TapDownDetails details) {
// live模式下禁用 锁定时🔒禁用
if (plPlayerController.videoType.value == 'live' ||
plPlayerController.controlsLock.value) {
return;
}
RenderBox renderBox =
_playerKey.currentContext!.findRenderObject() as RenderBox;
final double totalWidth = renderBox.size.width;
final double tapPosition = details.localPosition.dx;
final double sectionWidth = totalWidth / 4;
String type = 'left';
if (tapPosition < sectionWidth) {
type = 'left';
} else if (tapPosition < sectionWidth * 3) {
type = 'center';
} else {
type = 'right';
}
doubleTapFuc(type);
},
onLongPressStart: (LongPressStartDetails detail) {
plPlayerController.setLongPressStatus(true);
},
onLongPressEnd: (LongPressEndDetails details) {
plPlayerController.setLongPressStatus(false);
},
enableDragSubtitle: plPlayerController.enableDragSubtitle,
onUpdatePadding: plPlayerController.onUpdatePadding,
),
),
@@ -1155,143 +1281,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
// }
// }),
/// 手势
Positioned.fill(
left: 16,
top: 25,
right: 15,
bottom: 15,
child: Semantics(
label: '双击开关控件',
child: GestureDetector(
onVerticalDragStart: (details) {
if (plPlayerController.controlsLock.value) return;
if (details.localPosition.dy < 40) return;
if (details.localPosition.dx < 40) return;
if (details.localPosition.dx > context.width - 40) return;
if (details.localPosition.dy > context.height - 40) return;
_initialFocalPoint = details.localPosition;
_gestureType = null;
},
onVerticalDragUpdate: (details) {
if (plPlayerController.controlsLock.value) return;
if (plPlayerController.enableSlideVolumeBrightness.not &&
plPlayerController.enableSlideFS.not) {
return;
}
RenderBox renderBox =
_playerKey.currentContext!.findRenderObject() as RenderBox;
final double totalWidth = renderBox.size.width;
final double tapPosition = details.localPosition.dx;
final double sectionWidth = totalWidth / 3;
late String gestureType;
if (tapPosition < sectionWidth) {
if (plPlayerController.enableSlideVolumeBrightness.not) {
return;
}
// 左边区域
gestureType = 'left';
} else if (tapPosition < sectionWidth * 2) {
if (plPlayerController.enableSlideFS.not) {
return;
}
// 全屏
gestureType = 'center';
} else {
if (plPlayerController.enableSlideVolumeBrightness.not) {
return;
}
// 右边区域
gestureType = 'right';
}
if (_gestureType != null && _gestureType != gestureType) {
return;
}
_gestureType = gestureType;
if (_gestureType == 'left') {
// 左边区域 👈
final double level = renderBox.size.height * 3;
final double brightness =
_brightnessValue.value - details.delta.dy / level;
final double result = brightness.clamp(0.0, 1.0);
setBrightness(result);
} else if (_gestureType == 'center') {
// 全屏
const double threshold = 2.5; // 滑动阈值
double cumulativeDy =
details.localPosition.dy - _initialFocalPoint.dy;
void fullScreenTrigger(bool status) {
plPlayerController.triggerFullScreen(status: status);
}
if (cumulativeDy > threshold) {
_gestureType = 'center_down';
if (isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(fullScreenGestureReverse);
}
// debugPrint('center_down:$cumulativeDy');
} else if (cumulativeDy < -threshold) {
_gestureType = 'center_up';
if (!isFullScreen ^ fullScreenGestureReverse) {
fullScreenTrigger(!fullScreenGestureReverse);
}
// debugPrint('center_up:$cumulativeDy');
}
} else if (_gestureType == 'right') {
// 右边区域
final double level = renderBox.size.height * 0.5;
EasyThrottle.throttle(
'setVolume', const Duration(milliseconds: 20), () {
final double volume =
_volumeValue.value - details.delta.dy / level;
final double result = volume.clamp(0.0, 1.0);
setVolume(result);
});
}
},
onVerticalDragEnd: (details) {
interacting = false;
_initialFocalPoint = Offset.zero;
_gestureType = null;
},
onTap: () {
plPlayerController.controls =
!plPlayerController.showControls.value;
},
onDoubleTapDown: (TapDownDetails details) {
// live模式下禁用 锁定时🔒禁用
if (plPlayerController.videoType.value == 'live' ||
plPlayerController.controlsLock.value) {
return;
}
RenderBox renderBox =
_playerKey.currentContext!.findRenderObject() as RenderBox;
final double totalWidth = renderBox.size.width;
final double tapPosition = details.localPosition.dx;
final double sectionWidth = totalWidth / 4;
String type = 'left';
if (tapPosition < sectionWidth) {
type = 'left';
} else if (tapPosition < sectionWidth * 3) {
type = 'center';
} else {
type = 'right';
}
doubleTapFuc(type);
},
onLongPressStart: (LongPressStartDetails detail) {
plPlayerController.setLongPressStatus(true);
},
onLongPressEnd: (LongPressEndDetails details) {
plPlayerController.setLongPressStatus(false);
},
),
),
),
// 头部、底部控制条
Obx(
() => Positioned.fill(