Skip to content

Instantly share code, notes, and snippets.

@luo3house
Last active November 15, 2023 01:48
Show Gist options
  • Save luo3house/791cc7c9a655cc1d635aac06c904773d to your computer and use it in GitHub Desktop.
Save luo3house/791cc7c9a655cc1d635aac06c904773d to your computer and use it in GitHub Desktop.
Flutter: Gesture recognizer hanldes multiple taps, then draggable, useful for map dragging, image scaling (with example)
class MultiTapsToPanGestureRecognizer extends TapAndPanGestureRecognizer {
var minTapsToDrag = 1;
var timeoutToTaps = const Duration(milliseconds: 200);
@protected
var canDrag = false;
@protected
var firedDrag = false;
@protected
var firstTapms = 0;
@protected
var tapsBeforeTimeout = 0;
@protected
reset() {
firstTapms = 0;
tapsBeforeTimeout = 0;
canDrag = false;
firedDrag = false;
}
@override
void acceptGesture(int pointer) {
super.acceptGesture(pointer);
if (currentDown != null) {
final nowms = DateTime.now().millisecondsSinceEpoch;
final firstTapms = this.firstTapms;
if (nowms - firstTapms > timeoutToTaps.inMilliseconds) {
reset();
this.firstTapms = nowms;
tapsBeforeTimeout = 1;
} else {
tapsBeforeTimeout++;
}
}
if (tapsBeforeTimeout >= minTapsToDrag) {
tapsBeforeTimeout = 0;
firstTapms = 0;
canDrag = true;
}
if (currentUp != null && firedDrag) {
reset();
}
}
@override
void handleEvent(PointerEvent event) {
if (event is PointerMoveEvent) {
if (canDrag) {
firedDrag = true;
super.handleEvent(event);
}
} else {
super.handleEvent(event);
}
}
}
/// tap at least 2 times in 500ms, then drag
/// fires:
/// - on tap down in 2 times
/// - on drag start
/// - on drag update
Widget example() {
return RawGestureDetector(
behavior: HitTestBehavior.opaque,
gestures: {
MultiTapsToPanGestureRecognizer: GestureRecognizerFactoryWithHandlers<MultiTapsToPanGestureRecognizer>(
() => MultiTapsToPanGestureRecognizer(),
(recognizer) {
// configure handlers with
recognizer
// no slop
..gestureSettings = const DeviceGestureSettings(touchSlop: 0)
// tap at least 2 times, then draggable
..minTapsToDrag = 2
..onTapDown = (e) {}
..onDragUpdate = (e) {}
..onDragEnd = (e) {}
..onCancel = () {}
}
),
}
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment