improve player gesture

Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-05-09 13:50:07 +08:00
parent d63116542b
commit 23db485183
2 changed files with 166 additions and 236 deletions

View File

@@ -16,29 +16,30 @@ import 'package:vector_math/vector_math_64.dart' show Quad, Vector3;
class MouseInteractiveViewer extends StatefulWidget {
const MouseInteractiveViewer({
super.key,
this.clipBehavior = Clip.hardEdge,
this.panAxis = PanAxis.free,
this.boundaryMargin = EdgeInsets.zero,
this.clipBehavior = .hardEdge,
this.panAxis = .free,
this.boundaryMargin = .zero,
this.constrained = true,
this.maxScale = 2.5,
this.minScale = 0.8,
this.interactionEndFrictionCoefficient = _kDrag,
this.pointerSignalFallback,
required this.pointerSignalFallback,
this.onPointerPanZoomUpdate,
this.onPointerPanZoomEnd,
this.onPointerDown,
this.onInteractionEnd,
this.onInteractionStart,
this.onInteractionUpdate,
required this.onPointerDown,
required this.onPanEnd,
required this.onPanStart,
required this.onPanUpdate,
required this.onScaleUpdate,
this.panEnabled = true,
this.scaleEnabled = true,
this.scaleFactor = kDefaultMouseScrollToScaleFactor,
this.transformationController,
required this.transformationController,
this.alignment,
this.trackpadScrollCausesScale = false,
required this.childKey,
required this.child,
required this.onTranslate,
required this.scaleGestureRecognizer,
}) : assert(minScale > 0),
assert(interactionEndFrictionCoefficient > 0),
assert(maxScale > 0),
@@ -57,16 +58,17 @@ class MouseInteractiveViewer extends StatefulWidget {
final double maxScale;
final double minScale;
final double interactionEndFrictionCoefficient;
final PointerSignalEventListener? pointerSignalFallback;
final PointerSignalEventListener pointerSignalFallback;
final PointerPanZoomUpdateEventListener? onPointerPanZoomUpdate;
final PointerPanZoomEndEventListener? onPointerPanZoomEnd;
final PointerDownEventListener? onPointerDown;
final GestureScaleEndCallback? onInteractionEnd;
final GestureScaleStartCallback? onInteractionStart;
final GestureScaleUpdateCallback? onInteractionUpdate;
final TransformationController? transformationController;
final PointerDownEventListener onPointerDown;
final GestureScaleEndCallback onPanEnd;
final GestureScaleStartCallback onPanStart;
final GestureScaleUpdateCallback onPanUpdate;
final ValueChanged<double> onScaleUpdate;
final TransformationController transformationController;
final GlobalKey childKey;
final VoidCallback onTranslate;
final ScaleGestureRecognizer scaleGestureRecognizer;
static const double _kDrag = 0.0000135;
@@ -76,8 +78,7 @@ class MouseInteractiveViewer extends StatefulWidget {
class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
with TickerProviderStateMixin {
late TransformationController _transformer =
widget.transformationController ?? TransformationController();
late TransformationController _transformer;
final GlobalKey _parentKey = GlobalKey();
Animation<Offset>? _animation;
@@ -234,6 +235,9 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
widget.minScale,
widget.maxScale,
);
widget.onScaleUpdate(clampedTotalScale);
final double clampedScale = clampedTotalScale / currentScale;
return matrix.clone()
..scaleByDouble(clampedScale, clampedScale, clampedScale, 1);
@@ -270,10 +274,15 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
}
}
bool _isSinglePointer = false;
// Handle the start of a gesture. All of pan, scale, and rotate are handled
// with GestureDetector's scale gesture.
void _onScaleStart(ScaleStartDetails details) {
widget.onInteractionStart?.call(details);
if (_isSinglePointer = details.pointerCount == 1) {
widget.onPanStart(details);
return;
}
if (_controller.isAnimating) {
_controller
@@ -300,6 +309,11 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
// Handle an update to an ongoing gesture. All of pan, scale, and rotate are
// handled with GestureDetector's scale gesture.
void _onScaleUpdate(ScaleUpdateDetails details) {
if (_isSinglePointer) {
widget.onPanUpdate(details);
return;
}
final double scale = _transformer.value.getMaxScaleOnAxis();
_scaleAnimationFocalPoint = details.localFocalPoint;
final Offset focalPointScene = _transformer.toScene(
@@ -316,7 +330,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
_gestureType ??= _getGestureType(details);
}
if (!_gestureIsSupported(_gestureType)) {
widget.onInteractionUpdate?.call(details);
return;
}
@@ -356,7 +369,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
case _GestureType.rotate:
if (details.rotation == 0.0) {
widget.onInteractionUpdate?.call(details);
return;
}
final double desiredRotation = _rotationStart! + details.rotation;
@@ -373,7 +385,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
// In an effort to keep the behavior similar whether or not scaleEnabled
// is true, these gestures are thrown away.
if (details.scale != 1.0) {
widget.onInteractionUpdate?.call(details);
return;
}
_currentAxis ??= _getPanAxis(_referenceFocalPoint!, focalPointScene);
@@ -387,13 +398,16 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
);
_referenceFocalPoint = _transformer.toScene(details.localFocalPoint);
}
widget.onInteractionUpdate?.call(details);
}
// Handle the end of a gesture of _GestureType. All of pan, scale, and rotate
// are handled with GestureDetector's scale gesture.
void _onScaleEnd(ScaleEndDetails details) {
widget.onInteractionEnd?.call(details);
if (_isSinglePointer) {
widget.onPanEnd(details);
return;
}
_scaleStart = null;
_rotationStart = null;
_referenceFocalPoint = null;
@@ -481,10 +495,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
final double scaleChange;
if (event is PointerScrollEvent) {
if (event.kind == PointerDeviceKind.trackpad) {
widget.onInteractionStart?.call(
ScaleStartDetails(focalPoint: global, localFocalPoint: local),
);
final Offset localDelta = PointerEvent.transformDeltaViaPositions(
untransformedEndPosition: global + event.scrollDelta,
untransformedDelta: event.scrollDelta,
@@ -501,14 +511,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
newFocalPointScene - focalPointScene,
);
widget.onInteractionUpdate?.call(
ScaleUpdateDetails(
focalPoint: global - event.scrollDelta,
localFocalPoint: local - localDelta,
focalPointDelta: -localDelta,
),
);
widget.onInteractionEnd?.call(ScaleEndDetails());
return;
}
_handlePointerScrollEvent(event);
@@ -518,19 +520,8 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
} else {
return;
}
widget.onInteractionStart?.call(
ScaleStartDetails(focalPoint: global, localFocalPoint: local),
);
if (!_gestureIsSupported(_GestureType.scale)) {
widget.onInteractionUpdate?.call(
ScaleUpdateDetails(
focalPoint: global,
localFocalPoint: local,
scale: scaleChange,
),
);
widget.onInteractionEnd?.call(ScaleEndDetails());
return;
}
@@ -544,22 +535,12 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
_transformer.value,
focalPointSceneScaled - focalPointScene,
);
widget.onInteractionUpdate?.call(
ScaleUpdateDetails(
focalPoint: global,
localFocalPoint: local,
scale: scaleChange,
),
);
widget.onInteractionEnd?.call(ScaleEndDetails());
}
void _handlePointerScrollEvent(PointerScrollEvent event) {
final Offset local = event.localPosition;
final Offset global = event.position;
if (_gestureIsSupported(_GestureType.scale)) {
final Offset local = event.localPosition;
final Offset global = event.position;
if (HardwareKeyboard.instance.isControlPressed) {
_handleMouseWheelScale(event, local, global);
return;
@@ -569,16 +550,8 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
_handleMouseWheelPanAsScale(event, local, global, shift);
return;
}
widget.pointerSignalFallback?.call(event);
widget.pointerSignalFallback(event);
}
widget.onInteractionUpdate?.call(
ScaleUpdateDetails(
focalPoint: global,
localFocalPoint: local,
scale: math.exp(-event.scrollDelta.dy / widget.scaleFactor),
),
);
widget.onInteractionEnd?.call(ScaleEndDetails());
}
void _handleMouseWheelScale(
@@ -597,15 +570,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
_transformer.value,
focalPointSceneScaled - focalPointScene,
);
widget.onInteractionUpdate?.call(
ScaleUpdateDetails(
focalPoint: global,
localFocalPoint: local,
scale: scaleChange,
),
);
widget.onInteractionEnd?.call(ScaleEndDetails());
}
void _handleMouseWheelPanAsScale(
@@ -625,8 +589,6 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
_transformer.value,
newFocalPointScene - focalPointScene,
);
widget.onTranslate();
}
void _handleInertiaAnimation() {
@@ -675,33 +637,18 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
setState(() {});
}
void _onPointerDown(PointerDownEvent event) {
final localPosition = event.localPosition;
if (localPosition.dx < 40 || localPosition.dy < 40) {
return;
}
widget.onPointerDown?.call(event);
_scaleGestureRecognizer.addPointer(event);
}
@override
void initState() {
super.initState();
_scaleGestureRecognizer =
ScaleGestureRecognizer(
debugOwner: this,
dragStartBehavior: .start,
allowedButtonsFilter: (buttons) => buttons == kPrimaryButton,
trackpadScrollToScaleFactor: Offset(0, -1 / widget.scaleFactor),
trackpadScrollCausesScale: widget.trackpadScrollCausesScale,
)
..gestureSettings = gestureSettings
..onStart = _onScaleStart
..onUpdate = _onScaleUpdate
..onEnd = _onScaleEnd;
_scaleGestureRecognizer = widget.scaleGestureRecognizer
..gestureSettings = gestureSettings
..onStart = _onScaleStart
..onUpdate = _onScaleUpdate
..onEnd = _onScaleEnd;
_controller = AnimationController(vsync: this);
_scaleController = AnimationController(vsync: this);
_transformer = widget.transformationController;
_transformer.addListener(_handleTransformation);
}
@@ -709,28 +656,20 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
void didUpdateWidget(MouseInteractiveViewer oldWidget) {
super.didUpdateWidget(oldWidget);
final TransformationController? newController =
widget.transformationController;
final newController = widget.transformationController;
if (newController == oldWidget.transformationController) {
return;
}
_transformer.removeListener(_handleTransformation);
if (oldWidget.transformationController == null) {
_transformer.dispose();
}
_transformer = newController ?? TransformationController();
_transformer = newController;
_transformer.addListener(_handleTransformation);
}
@override
void dispose() {
_scaleGestureRecognizer.dispose();
_controller.dispose();
_scaleController.dispose();
_transformer.removeListener(_handleTransformation);
if (widget.transformationController == null) {
_transformer.dispose();
}
super.dispose();
}
@@ -742,7 +681,7 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
key: _parentKey,
behavior: HitTestBehavior.opaque,
onPointerSignal: _receivedPointerSignal,
onPointerDown: _onPointerDown,
onPointerDown: widget.onPointerDown,
onPointerPanZoomStart: _scaleGestureRecognizer.addPointerPanZoom,
onPointerPanZoomUpdate: widget.onPointerPanZoomUpdate,
onPointerPanZoomEnd: widget.onPointerPanZoomEnd,

View File

@@ -129,7 +129,7 @@ class PLVideoPlayer extends StatefulWidget {
class _PLVideoPlayerState extends State<PLVideoPlayer>
with WidgetsBindingObserver, TickerProviderStateMixin {
late AnimationController animationController;
late AnimationController _animationController;
late VideoController videoController;
late final CommonIntroController introController = widget.introController!;
late final VideoDetailController videoDetailController =
@@ -147,15 +147,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
late final RxBool showRestoreScaleBtn = false.obs;
GestureType? _gestureType;
Offset initialFocalPoint = Offset.zero;
//播放器放缩
bool interacting = false;
// 阅读器限制
// Timer? _accessibilityDebounce;
// double _lastAnnouncedValue = -1;
Offset? _initialFocalPoint;
bool _pauseDueToPauseUponEnteringBackgroundMode = false;
@@ -182,9 +174,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
if (visible) {
animationController.forward();
_animationController.forward();
} else {
animationController.reverse();
_animationController.reverse();
}
if (widget.videoDetailController case final controller?) {
@@ -218,9 +210,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
_onControlChanged,
);
transformationController = TransformationController();
_transformationController = TransformationController();
animationController = AnimationController(
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 100),
);
@@ -296,6 +288,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
_doubleTapGestureRecognizer = DoubleTapGestureRecognizer()
..onDoubleTapDown = _onDoubleTapDown;
_scaleGestureRecognizer = ScaleGestureRecognizer(
debugOwner: this,
dragStartBehavior: .start,
allowedButtonsFilter: (buttons) => buttons == kPrimaryButton,
trackpadScrollToScaleFactor: const Offset(
0,
-1 / kDefaultMouseScrollToScaleFactor,
),
trackpadScrollCausesScale: false,
);
}
@override
@@ -345,14 +348,15 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
_tapGestureRecognizer.dispose();
_longPressRecognizer?.dispose();
_doubleTapGestureRecognizer.dispose();
_scaleGestureRecognizer.dispose();
_brightnessListener?.cancel();
_controlsListener?.cancel();
animationController.dispose();
_animationController.dispose();
_transformationController.dispose();
_removeDmAction();
if (PlatformUtils.isMobile) {
FlutterVolumeController.removeListener();
}
transformationController.dispose();
_removeDmAction();
super.dispose();
}
@@ -923,7 +927,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
bool get isFullScreen => plPlayerController.isFullScreen.value;
late final TransformationController transformationController;
late final TransformationController _transformationController;
late ColorScheme colorScheme;
late double maxWidth;
@@ -935,84 +939,61 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
colorScheme = ColorScheme.of(context);
}
void _onInteractionStart(ScaleStartDetails details) {
if (plPlayerController.controlsLock.value) return;
// 如果起点太靠上则屏蔽
final localFocalPoint = details.localFocalPoint;
final dx = localFocalPoint.dx;
final dy = localFocalPoint.dy;
if (dx < 40 || dy < 40) return;
if (dx > maxWidth - 40 || dy > maxHeight - 40) return;
if (details.pointerCount > 1) {
interacting = true;
}
initialFocalPoint = localFocalPoint;
// if (kDebugMode) {
// debugPrint("_initialFocalPoint$_initialFocalPoint");
// }
void _onPanStart(ScaleStartDetails details) {
_gestureType = null;
_initialFocalPoint = details.localFocalPoint;
}
void _onInteractionUpdate(ScaleUpdateDetails details) {
showRestoreScaleBtn.value =
transformationController.value.storage[0] != 1.0;
if (interacting || initialFocalPoint == Offset.zero) {
return;
}
Offset cumulativeDelta = details.localFocalPoint - initialFocalPoint;
if (details.pointerCount > 1 && cumulativeDelta.distanceSquared < 2.25) {
interacting = true;
_gestureType = null;
return;
}
/// 锁定时禁用
if (plPlayerController.controlsLock.value) return;
void _onScaleUpdate(double scale) {
showRestoreScaleBtn.value = scale != 1.0;
}
void _onPanUpdate(ScaleUpdateDetails details) {
if (_gestureType == null) {
final cumulativeDelta = details.localFocalPoint - _initialFocalPoint!;
if (cumulativeDelta.distanceSquared < 1) return;
final dx = cumulativeDelta.dx.abs();
final dy = cumulativeDelta.dy.abs();
if (dx > 3 * dy) {
_gestureType = GestureType.horizontal;
_gestureType = .horizontal;
} else if (dy > 3 * dx) {
if (!plPlayerController.enableSlideVolumeBrightness &&
!plPlayerController.enableSlideFS) {
return;
}
// _gestureType = 'vertical';
final double tapPosition = details.localFocalPoint.dx;
final double sectionWidth = maxWidth / 3;
if (tapPosition < sectionWidth) {
if (PlatformUtils.isDesktop ||
!plPlayerController.enableSlideVolumeBrightness) {
if (!plPlayerController.enableSlideVolumeBrightness) {
return;
}
// 左边区域
_gestureType = GestureType.left;
if (PlatformUtils.isDesktop) {
_gestureType = .right;
} else {
_gestureType = .left;
}
} else if (tapPosition < sectionWidth * 2) {
if (!plPlayerController.enableSlideFS) {
return;
}
// 全屏
_gestureType = GestureType.center;
_gestureType = .center;
} else {
if (!plPlayerController.enableSlideVolumeBrightness) {
return;
}
// 右边区域
_gestureType = GestureType.right;
_gestureType = .right;
}
} else {
return;
}
return;
}
Offset delta = details.focalPointDelta;
if (_gestureType == GestureType.horizontal) {
if (_gestureType == .horizontal) {
// live模式下禁用
if (plPlayerController.isLive) return;
@@ -1074,39 +1055,37 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
plPlayerController.cancelSeek != true) {
plPlayerController.updatePreviewIndex(newPos ~/ 1000);
}
} else if (_gestureType == GestureType.left) {
} else if (_gestureType == .left) {
// 左边区域 👈
final double level = maxHeight * 3;
final double brightness = (_brightnessValue.value - delta.dy / level)
.clamp(0.0, 1.0);
setBrightness(brightness);
} else if (_gestureType == GestureType.center) {
} else if (_gestureType == .center) {
// 全屏
const double threshold = 2.5; // 滑动阈值
double cumulativeDy = details.localFocalPoint.dy - initialFocalPoint.dy;
double cumulativeDy = details.localFocalPoint.dy - _initialFocalPoint!.dy;
void fullScreenTrigger(bool status) {
plPlayerController.triggerFullScreen(status: status);
}
if (cumulativeDy > threshold) {
_gestureType = GestureType.center_down;
_gestureType = .center_down;
if (isFullScreen ^ plPlayerController.fullScreenGestureReverse) {
fullScreenTrigger(
plPlayerController.fullScreenGestureReverse,
);
}
// if (kDebugMode) debugPrint('center_down:$cumulativeDy');
} else if (cumulativeDy < -threshold) {
_gestureType = GestureType.center_up;
_gestureType = .center_up;
if (!isFullScreen ^ plPlayerController.fullScreenGestureReverse) {
fullScreenTrigger(
!plPlayerController.fullScreenGestureReverse,
);
}
// if (kDebugMode) debugPrint('center_up:$cumulativeDy');
}
} else if (_gestureType == GestureType.right) {
} else if (_gestureType == .right) {
// 右边区域
final double level = maxHeight * 0.5;
EasyThrottle.throttle(
@@ -1124,7 +1103,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
}
void _onInteractionEnd(ScaleEndDetails details) {
void _onPanEnd(ScaleEndDetails details) {
if (Platform.isAndroid &&
_gestureType == .left &&
plPlayerController.setSystemBrightness) {
@@ -1146,8 +1125,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
plPlayerController.onChangedSliderEnd();
}
interacting = false;
initialFocalPoint = Offset.zero;
_initialFocalPoint = null;
_gestureType = null;
}
@@ -1168,25 +1146,10 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
plPlayerController.doubleTapFuc(type);
}
void onTapDesktop() {
if (plPlayerController.isLive || plPlayerController.controlsLock.value) {
return;
}
plPlayerController.onDoubleTapCenter();
}
void onDoubleTapDesktop() {
if (plPlayerController.controlsLock.value) {
return;
}
plPlayerController.triggerFullScreen(status: !isFullScreen);
}
void _onTapUp(TapUpDetails details) {
switch (details.kind) {
case ui.PointerDeviceKind.mouse when PlatformUtils.isDesktop:
onTapDesktop();
break;
plPlayerController.onDoubleTapCenter();
default:
if (_suspendedDm == null) {
plPlayerController.controls = !plPlayerController.showControls.value;
@@ -1195,7 +1158,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
} else {
_suspendedDm = null;
}
break;
}
}
@@ -1225,11 +1187,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
void _onDoubleTapDown(TapDownDetails details) {
switch (details.kind) {
case ui.PointerDeviceKind.mouse when PlatformUtils.isDesktop:
onDoubleTapDesktop();
break;
plPlayerController.triggerFullScreen(status: !isFullScreen);
default:
onDoubleTapDownMobile(details);
break;
}
}
@@ -1247,8 +1207,21 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
plPlayerController.setLongPressStatus(false));
late final ImmediateTapGestureRecognizer _tapGestureRecognizer;
late final DoubleTapGestureRecognizer _doubleTapGestureRecognizer;
late final ScaleGestureRecognizer _scaleGestureRecognizer;
StreamSubscription<bool>? _danmakuListener;
static const _kOffsetThreshold = 40.0;
bool _isPositionAllowed(Offset offset) {
if (offset.dx < _kOffsetThreshold ||
offset.dy < _kOffsetThreshold ||
offset.dx > maxWidth - _kOffsetThreshold ||
offset.dy > maxHeight - _kOffsetThreshold) {
return false;
}
return true;
}
void _onPointerDown(PointerDownEvent event) {
if (PlatformUtils.isDesktop) {
final buttons = event.buttons;
@@ -1260,20 +1233,37 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
..controlsLock.value = false
..showControls.value = false;
}
plPlayerController
.triggerFullScreen(
status: !isFullScreen,
inAppFullScreen: isSecondaryBtn,
)
.whenComplete(() => initialFocalPoint = Offset.zero);
plPlayerController.triggerFullScreen(
status: !isFullScreen,
inAppFullScreen: isSecondaryBtn,
);
return;
}
}
_tapGestureRecognizer.addPointer(event);
_doubleTapGestureRecognizer.addPointer(event);
if (!plPlayerController.isLive) {
longPressRecognizer.addPointer(event);
if (_isPositionAllowed(event.localPosition)) {
final controlsUnlock = !plPlayerController.controlsLock.value;
if (PlatformUtils.isMobile) {
_tapGestureRecognizer.addPointer(event);
if (controlsUnlock) {
if (!plPlayerController.isLive) {
_doubleTapGestureRecognizer.addPointer(event);
longPressRecognizer.addPointer(event);
}
_scaleGestureRecognizer.addPointer(event);
}
} else {
if (controlsUnlock) {
if (!plPlayerController.isLive) {
_tapGestureRecognizer.addPointer(event);
}
_doubleTapGestureRecognizer.addPointer(event);
if (!plPlayerController.isLive) {
longPressRecognizer.addPointer(event);
}
_scaleGestureRecognizer.addPointer(event);
}
}
}
}
@@ -1285,17 +1275,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
final dx = pan.dx.abs();
final dy = pan.dy.abs();
if (dx > 3 * dy) {
_gestureType = GestureType.horizontal;
_gestureType = .horizontal;
} else if (dy > 3 * dx) {
_gestureType = GestureType.right;
_gestureType = .right;
}
return;
}
if (_gestureType == GestureType.horizontal) {
if (_gestureType == .horizontal) {
if (plPlayerController.isLive) return;
Offset delta = event.localPanDelta;
final delta = event.localPanDelta;
final int curSliderPosition =
plPlayerController.sliderPosition.inMilliseconds;
final int newPos =
@@ -1317,7 +1307,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
plPlayerController.cancelSeek != true) {
plPlayerController.updatePreviewIndex(newPos ~/ 1000);
}
} else if (_gestureType == GestureType.right) {
} else if (_gestureType == .right) {
if (!plPlayerController.enableSlideVolumeBrightness) {
return;
}
@@ -1339,6 +1329,12 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
void _onPointerPanZoomEnd(PointerPanZoomEndEvent event) {
plPlayerController.showPreview.value = false;
if (plPlayerController.isSliderMoving.value) {
plPlayerController
..seekTo(plPlayerController.sliderPosition, isSeek: false)
..onChangedSliderEnd();
}
_gestureType = null;
}
@@ -1619,7 +1615,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
children: [
AppBarAni(
isTop: true,
controller: animationController,
controller: _animationController,
isFullScreen: isFullScreen,
removeSafeArea: plPlayerController.removeSafeArea,
child: plPlayerController.isDesktopPip
@@ -1632,7 +1628,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
),
AppBarAni(
isTop: false,
controller: animationController,
controller: _animationController,
isFullScreen: isFullScreen,
removeSafeArea: plPlayerController.removeSafeArea,
child:
@@ -1697,12 +1693,12 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
);
final anim = animController.drive(
Matrix4Tween(
begin: transformationController.value,
begin: _transformationController.value,
end: Matrix4.identity(),
).chain(CurveTween(curve: Curves.easeOut)),
);
void listener() {
transformationController.value = anim.value;
_transformationController.value = anim.value;
}
animController.addListener(listener);
@@ -2035,7 +2031,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
Widget get _videoWidget {
return Container(
clipBehavior: Clip.none,
clipBehavior: .none,
width: maxWidth,
height: maxHeight,
color: widget.fill,
@@ -2046,24 +2042,19 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
onPointerPanZoomUpdate: _onPointerPanZoomUpdate,
onPointerPanZoomEnd: _onPointerPanZoomEnd,
onPointerDown: _onPointerDown,
onInteractionStart: _onInteractionStart,
onInteractionUpdate: _onInteractionUpdate,
onInteractionEnd: _onInteractionEnd,
onPanStart: _onPanStart,
onPanUpdate: _onPanUpdate,
onPanEnd: _onPanEnd,
onScaleUpdate: _onScaleUpdate,
scaleGestureRecognizer: _scaleGestureRecognizer,
panEnabled: false,
minScale: plPlayerController.enableShrinkVideoSize ? 0.75 : 1,
maxScale: 2.0,
boundaryMargin: plPlayerController.enableShrinkVideoSize
? const EdgeInsets.all(double.infinity)
: EdgeInsets.zero,
panAxis: PanAxis.aligned,
transformationController: transformationController,
onTranslate: () {
final storage = transformationController.value.storage;
showRestoreScaleBtn.value =
storage[12].abs() > 2.0 ||
storage[13].abs() > 2.0 ||
storage[0] != 1.0;
},
? const .all(double.infinity)
: .zero,
panAxis: .aligned,
transformationController: _transformationController,
childKey: _videoKey,
child: RepaintBoundary(
key: _videoKey,