From 23db4851830c1537329779eb7018bcb283f52d64 Mon Sep 17 00:00:00 2001 From: dom Date: Sat, 9 May 2026 13:50:07 +0800 Subject: [PATCH] improve player gesture Signed-off-by: dom --- .../gesture/mouse_interactive_viewer.dart | 163 ++++-------- lib/plugin/pl_player/view/view.dart | 239 +++++++++--------- 2 files changed, 166 insertions(+), 236 deletions(-) diff --git a/lib/common/widgets/gesture/mouse_interactive_viewer.dart b/lib/common/widgets/gesture/mouse_interactive_viewer.dart index bffbeccec..a2b0e6cf9 100644 --- a/lib/common/widgets/gesture/mouse_interactive_viewer.dart +++ b/lib/common/widgets/gesture/mouse_interactive_viewer.dart @@ -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 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 with TickerProviderStateMixin { - late TransformationController _transformer = - widget.transformationController ?? TransformationController(); + late TransformationController _transformer; final GlobalKey _parentKey = GlobalKey(); Animation? _animation; @@ -234,6 +235,9 @@ class _MouseInteractiveViewerState extends State 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 } } + 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 // 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 _gestureType ??= _getGestureType(details); } if (!_gestureIsSupported(_gestureType)) { - widget.onInteractionUpdate?.call(details); return; } @@ -356,7 +369,6 @@ class _MouseInteractiveViewerState extends State 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 // 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 ); _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 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 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 } 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 _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 _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 _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 _transformer.value, newFocalPointScene - focalPointScene, ); - - widget.onTranslate(); } void _handleInertiaAnimation() { @@ -675,33 +637,18 @@ class _MouseInteractiveViewerState extends State 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 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 key: _parentKey, behavior: HitTestBehavior.opaque, onPointerSignal: _receivedPointerSignal, - onPointerDown: _onPointerDown, + onPointerDown: widget.onPointerDown, onPointerPanZoomStart: _scaleGestureRecognizer.addPointerPanZoom, onPointerPanZoomUpdate: widget.onPointerPanZoomUpdate, onPointerPanZoomEnd: widget.onPointerPanZoomEnd, diff --git a/lib/plugin/pl_player/view/view.dart b/lib/plugin/pl_player/view/view.dart index 80b206bcb..3ebf82cb0 100644 --- a/lib/plugin/pl_player/view/view.dart +++ b/lib/plugin/pl_player/view/view.dart @@ -129,7 +129,7 @@ class PLVideoPlayer extends StatefulWidget { class _PLVideoPlayerState extends State 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 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 } 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 _onControlChanged, ); - transformationController = TransformationController(); + _transformationController = TransformationController(); - animationController = AnimationController( + _animationController = AnimationController( vsync: this, duration: const Duration(milliseconds: 100), ); @@ -296,6 +288,17 @@ class _PLVideoPlayerState extends State _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 _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 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 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 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 } } - void _onInteractionEnd(ScaleEndDetails details) { + void _onPanEnd(ScaleEndDetails details) { if (Platform.isAndroid && _gestureType == .left && plPlayerController.setSystemBrightness) { @@ -1146,8 +1125,7 @@ class _PLVideoPlayerState extends State } plPlayerController.onChangedSliderEnd(); } - interacting = false; - initialFocalPoint = Offset.zero; + _initialFocalPoint = null; _gestureType = null; } @@ -1168,25 +1146,10 @@ class _PLVideoPlayerState extends State 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 } else { _suspendedDm = null; } - break; } } @@ -1225,11 +1187,9 @@ class _PLVideoPlayerState extends State 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 plPlayerController.setLongPressStatus(false)); late final ImmediateTapGestureRecognizer _tapGestureRecognizer; late final DoubleTapGestureRecognizer _doubleTapGestureRecognizer; + late final ScaleGestureRecognizer _scaleGestureRecognizer; + StreamSubscription? _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 ..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 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 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 } 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 children: [ AppBarAni( isTop: true, - controller: animationController, + controller: _animationController, isFullScreen: isFullScreen, removeSafeArea: plPlayerController.removeSafeArea, child: plPlayerController.isDesktopPip @@ -1632,7 +1628,7 @@ class _PLVideoPlayerState extends State ), AppBarAni( isTop: false, - controller: animationController, + controller: _animationController, isFullScreen: isFullScreen, removeSafeArea: plPlayerController.removeSafeArea, child: @@ -1697,12 +1693,12 @@ class _PLVideoPlayerState extends State ); 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 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 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,