opt image viewer gesture

Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-03-20 13:55:34 +08:00
parent ae59d257c3
commit 236b524445
3 changed files with 188 additions and 81 deletions

View File

@@ -1,26 +1,29 @@
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:flutter/gestures.dart';
class CustomHorizontalDragGestureRecognizer
extends HorizontalDragGestureRecognizer {
CustomHorizontalDragGestureRecognizer({
super.debugOwner,
super.supportedDevices,
super.allowedButtonsFilter,
});
mixin InitialPositionMixin on GestureRecognizer {
Offset? _initialPosition;
Offset? get initialPosition => _initialPosition;
@override
DeviceGestureSettings get gestureSettings => _gestureSettings;
final _gestureSettings = DeviceGestureSettings(touchSlop: touchSlopH);
@override
void addAllowedPointer(PointerDownEvent event) {
super.addAllowedPointer(event);
_initialPosition = event.position;
}
}
class CustomHorizontalDragGestureRecognizer
extends HorizontalDragGestureRecognizer
with InitialPositionMixin {
CustomHorizontalDragGestureRecognizer({
super.debugOwner,
super.supportedDevices,
super.allowedButtonsFilter,
});
@override
DeviceGestureSettings get gestureSettings => _gestureSettings;
final _gestureSettings = DeviceGestureSettings(touchSlop: touchSlopH);
@override
bool hasSufficientGlobalDistanceToAccept(
@@ -41,7 +44,7 @@ double touchSlopH = Pref.touchSlopH;
bool _computeHitSlop(
double globalDistanceMoved,
DeviceGestureSettings? settings,
DeviceGestureSettings settings,
PointerDeviceKind kind,
Offset? initialPosition,
Offset lastPosition,
@@ -53,10 +56,10 @@ bool _computeHitSlop(
case PointerDeviceKind.invertedStylus:
case PointerDeviceKind.unknown:
case PointerDeviceKind.touch:
return globalDistanceMoved > touchSlopH &&
return globalDistanceMoved > settings.touchSlop! &&
_calc(initialPosition!, lastPosition);
case PointerDeviceKind.trackpad:
return globalDistanceMoved > (settings?.touchSlop ?? kTouchSlop);
return globalDistanceMoved > settings.touchSlop!;
}
}

View File

@@ -1,22 +1,22 @@
import 'package:PiliPlus/common/widgets/gesture/horizontal_drag_gesture_recognizer.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:flutter/gestures.dart';
mixin ImageGestureRecognizerMixin on GestureRecognizer {
int? _pointer;
@override
void addPointer(PointerDownEvent event) {
void addPointer(PointerDownEvent event, {bool isPointerAllowed = true}) {
if (_pointer == event.pointer) {
return;
}
_pointer = event.pointer;
super.addPointer(event);
if (isPointerAllowed) {
super.addPointer(event);
}
}
}
typedef IsBoundaryAllowed =
bool Function(Offset? initialPosition, OffsetPair lastPosition);
class ImageHorizontalDragGestureRecognizer
extends CustomHorizontalDragGestureRecognizer
with ImageGestureRecognizerMixin {
@@ -26,23 +26,62 @@ class ImageHorizontalDragGestureRecognizer
super.allowedButtonsFilter,
});
IsBoundaryAllowed? isBoundaryAllowed;
static final double _touchSlop = PlatformUtils.isDesktop
? kPrecisePointerHitSlop
: 3.0;
@override
bool hasSufficientGlobalDistanceToAccept(
PointerDeviceKind pointerDeviceKind,
double? deviceTouchSlop,
) {
return super.hasSufficientGlobalDistanceToAccept(
pointerDeviceKind,
deviceTouchSlop,
) &&
(isBoundaryAllowed?.call(initialPosition, lastPosition) ?? true);
DeviceGestureSettings get gestureSettings => _gestureSettings;
final _gestureSettings = DeviceGestureSettings(touchSlop: _touchSlop);
bool isAtLeftEdge = false;
bool isAtRightEdge = false;
void setAtBothEdges() {
isAtLeftEdge = isAtRightEdge = true;
}
bool _isEdgeAllowed(double dx) {
if ((initialPosition!.dx - dx).abs() < _touchSlop) return true;
if (isAtLeftEdge) {
if (isAtRightEdge) {
return _hasAcceptedOrChecked = true;
}
_hasAcceptedOrChecked = true;
return initialPosition!.dx < dx;
} else if (isAtRightEdge) {
_hasAcceptedOrChecked = true;
return initialPosition!.dx > dx;
}
return true;
}
@override
void dispose() {
isBoundaryAllowed = null;
super.dispose();
void handleEvent(PointerEvent event) {
if (!_hasAcceptedOrChecked &&
event is PointerMoveEvent &&
_pointer == event.pointer) {
if (!_isEdgeAllowed(event.position.dx)) {
rejectGesture(event.pointer);
return;
}
}
super.handleEvent(event);
}
bool _hasAcceptedOrChecked = false;
@override
void acceptGesture(int pointer) {
_hasAcceptedOrChecked = true;
super.acceptGesture(pointer);
}
@override
void stopTrackingPointer(int pointer) {
_hasAcceptedOrChecked = false;
isAtLeftEdge = false;
isAtRightEdge = false;
super.stopTrackingPointer(pointer);
}
}