Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OnTap PDF to some buttons appear #76

Closed
VanessaSwerts opened this issue Jun 11, 2020 · 3 comments
Closed

OnTap PDF to some buttons appear #76

VanessaSwerts opened this issue Jun 11, 2020 · 3 comments

Comments

@VanessaSwerts
Copy link

In the application I am developing, I needed that when I click on the PDF just once (onTap), some buttons appear under the PDF. But InkWell and gestureDetector are not working with PDFView. How could I implement gestureRecognizers to do this?

@endigo
Copy link
Owner

endigo commented Jun 19, 2020

You can use the following code .

gestureRecognizers: Set()
              ..add(
                  Factory<TapGestureRecognizer>(() => TapGestureRecognizer()
                    ..onTapDown = (tap) {
                      print("This one prints");
                    })),

@jerilMJ
Copy link

jerilMJ commented Jun 19, 2020

onTapDown has a slight delay as compared to onTap so it may seem undesirable in some cases. I was working on a workaround and I have finally got a satisfactory result. This should detect taps while letting through other gestures. It involves extending the OneSequenceGestureRecognizer class and overriding its methods.

Here is the code:

class CustomTapGestureRecognizer extends OneSequenceGestureRecognizer {
  int _selectedPointer;

  // Initial Position of selected pointer
  Offset _initialPos;

  // Timestamp of first pointer (selected) update
  Duration _first;

  // Timestamp of latest pointer (selected) update
  Duration _last;

  // Signifies that the event is potentially a tap
  bool _isPotentiallyTap = false;

  // For future taps
  bool _isGoingToFire = false;

  Function onTap;

  // Reset everything for a new session
  void _resetState() {
    _isGoingToFire = false;
    _isPotentiallyTap = false;
    _selectedPointer = null;
    _initialPos = null;
    _first = null;
    _last = null;
  }

  @override
  void addPointer(PointerDownEvent event) {
    startTrackingPointer(event.pointer);
    if (_selectedPointer == null) {
      // Select the first pointer that comes through
      _selectedPointer = event.pointer;
      _isPotentiallyTap = true;
    } else {
      // Multiple pointers on the screen which means it's not a tap
      _selectedPointer = null;
      _isPotentiallyTap = false;
    }

    // Accept all. Rejecting might lead to other gestures not working
    resolve(GestureDisposition.accepted);

    // If previous pointer was going to fire [onTap], stop it.
    // Used to prevent onTap being fired on multi-tap.
    if (_isGoingToFire) {
      _resetState();
    }
  }

  @override
  String get debugDescription => 'only one pointer recognizer';

  @override
  void didStopTrackingLastPointer(int pointer) {}

  @override
  void handleEvent(PointerEvent event) {
    // onPointerUp, see if it moved and see the duration of its
    // interaction on the screen. If it moved, it's not a tap.
    // If its duration is more than 125 milliseconds (default
    // Android tapTimeout), it's not a tap.
    if (!event.down && event.pointer == _selectedPointer) {
      _last = event.timeStamp;

      if (event.localPosition.distanceSquared ==
              (_initialPos?.distanceSquared ??
                  event.localPosition.distanceSquared) &&
          (_last.inMilliseconds - _first.inMilliseconds) <= 125) {
        _isGoingToFire = true;

        // Presenting a slight delay to consider multi-tap case
        Future.delayed(const Duration(milliseconds: 250), () {
          if (_isPotentiallyTap) {
            onTap();
          }
          _resetState();
        });
      } else {
        _resetState();
      }
    } else if (_initialPos == null) {
      // Get initialPos and time
      _initialPos = event.localPosition;
      _first = event.timeStamp;
    }
  }
}

And now, add it to the gestureRecognizers argument of PDFView:

  PDFView(
               ....
                gestureRecognizers: Set()
                  ..add(
                    Factory<CustomTapGestureRecognizer>(
                      () => CustomTapGestureRecognizer()
                        ..onTap = () {
                          // make the buttons appear here
                        },
                    ),
                  ),
  ),

It might seem a bit long but it works pretty good. Hope it helps! :)

@VanessaSwerts
Copy link
Author

Thank you so much for the help of both , its works very well.

@endigo endigo closed this as completed Jun 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants