mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 03:06:59 +08:00
feat: ImmediateTapGestureRecognizer (#1572)
This commit is contained in:
committed by
GitHub
parent
84f972a3ab
commit
a2d5ecc51e
180
lib/common/widgets/gesture/immediate_tap_gesture_recognizer.dart
Normal file
180
lib/common/widgets/gesture/immediate_tap_gesture_recognizer.dart
Normal file
@@ -0,0 +1,180 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
|
||||
class ImmediateTapGestureRecognizer extends OneSequenceGestureRecognizer {
|
||||
ImmediateTapGestureRecognizer({
|
||||
super.debugOwner,
|
||||
super.supportedDevices,
|
||||
super.allowedButtonsFilter,
|
||||
required this.onTapDown,
|
||||
required this.onTapUp,
|
||||
required this.onTapCancel,
|
||||
this.onTap,
|
||||
});
|
||||
|
||||
final GestureTapDownCallback onTapDown;
|
||||
|
||||
final GestureTapUpCallback onTapUp;
|
||||
|
||||
final GestureTapCancelCallback onTapCancel;
|
||||
|
||||
final GestureTapCallback? onTap;
|
||||
|
||||
PointerUpEvent? _up;
|
||||
int _activePointer = 0;
|
||||
bool _sentTapDown = false;
|
||||
bool _wonArena = false;
|
||||
|
||||
@override
|
||||
bool isPointerPanZoomAllowed(PointerPanZoomStartEvent event) => false;
|
||||
|
||||
@override
|
||||
bool isPointerAllowed(PointerDownEvent event) =>
|
||||
_activePointer == 0 && super.isPointerAllowed(event);
|
||||
|
||||
@override
|
||||
void addAllowedPointer(PointerDownEvent event) {
|
||||
super.addAllowedPointer(event);
|
||||
|
||||
_activePointer = event.pointer;
|
||||
_sentTapDown = false;
|
||||
_wonArena = false;
|
||||
}
|
||||
|
||||
@override
|
||||
void handleEvent(PointerEvent event) {
|
||||
if (event.pointer != _activePointer) {
|
||||
stopTrackingPointer(event.pointer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event is PointerDownEvent) {
|
||||
_handleTapDown(event);
|
||||
} else if (event is PointerMoveEvent) {
|
||||
_handlePointerMove(event);
|
||||
} else if (event is PointerUpEvent) {
|
||||
_up = event;
|
||||
_handlePointerUp(event);
|
||||
}
|
||||
|
||||
stopTrackingIfPointerNoLongerDown(event);
|
||||
}
|
||||
|
||||
void _handleTapDown(PointerDownEvent event) {
|
||||
if (_sentTapDown) return;
|
||||
|
||||
_sentTapDown = true;
|
||||
final details = TapDownDetails(
|
||||
globalPosition: event.position,
|
||||
localPosition: event.localPosition,
|
||||
kind: event.kind,
|
||||
);
|
||||
invokeCallback<void>('onTapDown', () => onTapDown(details));
|
||||
}
|
||||
|
||||
void _handlePointerMove(PointerMoveEvent event) {
|
||||
if (event.delta.distanceSquared > 2.0) {
|
||||
_cancelGesture('pointer moved');
|
||||
stopTrackingPointer(event.pointer);
|
||||
}
|
||||
}
|
||||
|
||||
void _handlePointerUp(PointerUpEvent event) {
|
||||
if (_wonArena && _sentTapDown) {
|
||||
_handleTapUp(event);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleTapUp(PointerUpEvent event) {
|
||||
if (_sentTapDown) {
|
||||
final details = TapUpDetails(
|
||||
globalPosition: event.position,
|
||||
localPosition: event.localPosition,
|
||||
kind: event.kind,
|
||||
);
|
||||
invokeCallback<void>('onTapUp', () => onTapUp(details));
|
||||
|
||||
if (onTap != null) {
|
||||
invokeCallback<void>('onTap', onTap!);
|
||||
}
|
||||
}
|
||||
|
||||
_reset();
|
||||
}
|
||||
|
||||
void _cancelGesture(String reason) {
|
||||
if (_sentTapDown) {
|
||||
invokeCallback<void>('onTapCancel: $reason', onTapCancel);
|
||||
}
|
||||
_reset();
|
||||
}
|
||||
|
||||
void _reset() {
|
||||
_activePointer = 0;
|
||||
_up = null;
|
||||
_sentTapDown = false;
|
||||
_wonArena = false;
|
||||
}
|
||||
|
||||
@override
|
||||
void acceptGesture(int pointer) {
|
||||
super.acceptGesture(pointer);
|
||||
|
||||
if (pointer == _activePointer) {
|
||||
_wonArena = true;
|
||||
|
||||
if (_up != null && _sentTapDown) {
|
||||
_handleTapUp(_up!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void rejectGesture(int pointer) {
|
||||
super.rejectGesture(pointer);
|
||||
|
||||
if (pointer == _activePointer) {
|
||||
_cancelGesture('gesture rejected by arena');
|
||||
stopTrackingPointer(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didStopTrackingLastPointer(int pointer) {
|
||||
// wait for arena
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_sentTapDown) {
|
||||
_cancelGesture('disposed');
|
||||
}
|
||||
_reset();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
String get debugDescription => 'immediate tap';
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties
|
||||
..add(IntProperty('activePointer', _activePointer))
|
||||
..add(
|
||||
FlagProperty(
|
||||
'sentTapDown',
|
||||
value: _sentTapDown,
|
||||
ifTrue: 'has sentTapDown',
|
||||
),
|
||||
)
|
||||
..add(FlagProperty('wonArena', value: _wonArena, ifTrue: 'wonArena'))
|
||||
..add(
|
||||
DiagnosticsProperty<PointerUpEvent>(
|
||||
'pointerUpEvent',
|
||||
_up,
|
||||
defaultValue: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user