| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- import 'dart:async';
- import 'package:flutter/gestures.dart';
- import 'package:flutter/widgets.dart';
- class TerminalGestureDetector extends StatefulWidget {
- const TerminalGestureDetector({
- super.key,
- this.child,
- this.onSingleTapUp,
- this.onTapUp,
- this.onTapDown,
- this.onSecondaryTapDown,
- this.onSecondaryTapUp,
- this.onTertiaryTapDown,
- this.onTertiaryTapUp,
- this.onLongPressStart,
- this.onLongPressMoveUpdate,
- this.onLongPressUp,
- this.onDragStart,
- this.onDragUpdate,
- this.onDoubleTapDown,
- });
- final Widget? child;
- final GestureTapUpCallback? onTapUp;
- final GestureTapUpCallback? onSingleTapUp;
- final GestureTapDownCallback? onTapDown;
- final GestureTapDownCallback? onSecondaryTapDown;
- final GestureTapUpCallback? onSecondaryTapUp;
- final GestureTapDownCallback? onDoubleTapDown;
- final GestureTapDownCallback? onTertiaryTapDown;
- final GestureTapUpCallback? onTertiaryTapUp;
- final GestureLongPressStartCallback? onLongPressStart;
- final GestureLongPressMoveUpdateCallback? onLongPressMoveUpdate;
- final GestureLongPressUpCallback? onLongPressUp;
- final GestureDragStartCallback? onDragStart;
- final GestureDragUpdateCallback? onDragUpdate;
- @override
- State<TerminalGestureDetector> createState() =>
- _TerminalGestureDetectorState();
- }
- class _TerminalGestureDetectorState extends State<TerminalGestureDetector> {
- Timer? _doubleTapTimer;
- Offset? _lastTapOffset;
- // True if a second tap down of a double tap is detected. Used to discard
- // subsequent tap up / tap hold of the same tap.
- bool _isDoubleTap = false;
- // The down handler is force-run on success of a single tap and optimistically
- // run before a long press success.
- void _handleTapDown(TapDownDetails details) {
- widget.onTapDown?.call(details);
- if (_doubleTapTimer != null &&
- _isWithinDoubleTapTolerance(details.globalPosition)) {
- // If there was already a previous tap, the second down hold/tap is a
- // double tap down.
- widget.onDoubleTapDown?.call(details);
- _doubleTapTimer!.cancel();
- _doubleTapTimeout();
- _isDoubleTap = true;
- }
- }
- void _handleTapUp(TapUpDetails details) {
- if (!_isDoubleTap) {
- widget.onSingleTapUp?.call(details);
- _lastTapOffset = details.globalPosition;
- _doubleTapTimer = Timer(kDoubleTapTimeout, _doubleTapTimeout);
- }
- _isDoubleTap = false;
- }
- void _doubleTapTimeout() {
- _doubleTapTimer = null;
- _lastTapOffset = null;
- }
- bool _isWithinDoubleTapTolerance(Offset secondTapOffset) {
- if (_lastTapOffset == null) {
- return false;
- }
- final Offset difference = secondTapOffset - _lastTapOffset!;
- return difference.distance <= kDoubleTapSlop;
- }
- @override
- Widget build(BuildContext context) {
- final gestures = <Type, GestureRecognizerFactory>{};
- gestures[TapGestureRecognizer] =
- GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
- () => TapGestureRecognizer(debugOwner: this),
- (TapGestureRecognizer instance) {
- instance
- ..onTapDown = _handleTapDown
- ..onTapUp = _handleTapUp
- ..onSecondaryTapDown = widget.onSecondaryTapDown
- ..onSecondaryTapUp = widget.onSecondaryTapUp
- ..onTertiaryTapDown = widget.onTertiaryTapDown
- ..onTertiaryTapUp = widget.onTertiaryTapUp;
- },
- );
- gestures[LongPressGestureRecognizer] =
- GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
- () => LongPressGestureRecognizer(
- debugOwner: this,
- supportedDevices: {
- PointerDeviceKind.touch,
- // PointerDeviceKind.mouse, // for debugging purposes only
- },
- ),
- (LongPressGestureRecognizer instance) {
- instance
- ..onLongPressStart = widget.onLongPressStart
- ..onLongPressMoveUpdate = widget.onLongPressMoveUpdate
- ..onLongPressUp = widget.onLongPressUp;
- },
- );
- gestures[PanGestureRecognizer] =
- GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
- () => PanGestureRecognizer(
- debugOwner: this,
- supportedDevices: <PointerDeviceKind>{PointerDeviceKind.mouse},
- ),
- (PanGestureRecognizer instance) {
- instance
- ..dragStartBehavior = DragStartBehavior.down
- ..onStart = widget.onDragStart
- ..onUpdate = widget.onDragUpdate;
- },
- );
- return RawGestureDetector(
- gestures: gestures,
- excludeFromSemantics: true,
- child: widget.child,
- );
- }
- }
|