Search code examples
iosswiftuiscrollviewuigesturerecognizeruitapgesturerecognizer

Adding a UITapGesture to UIScrollView


I have a UIScrollView. I put a tap gesture to it as this:

self.tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapped(_:)))
self.tapGesture.delegate = self
self.tapGesture.numberOfTapsRequired = 1
self.tapGesture.numberOfTouchesRequired = 1
self.tapGesture.cancelsTouchesInView = false
self.tapGesture.delaysTouchesBegan = false
self.tapGesture.delaysTouchesEnded = false
self.scrollView.addGestureRecognizer(self.tapGesture)

This works fine, except when the scrollview is scrolling (scrolling animation is happening, not user dragging), tap gesture is ignored.

How I am animating the scroll view:

UIView.animate(withDuration: 0.3, delay: 0.0,
                           options:[.beginFromCurrentState, .curveEaseInOut], animations:
    {
        self.scrollView.contentOffset = CGPoint(x:self.scrollView.contentOffset.x, y:yOffset)
    },  completion: nil)

This scrollview is scrolling most the time and I am trying to get it to recognize the tap gesture while scroll view is animating scrolling ....


Solution

  • Take a look at the UIGestureRecogniserDelegate functions.

    You should be able to specify that both the pan and tap gestures can be recognised at the same time with the following function:

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, 
    shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return (gestureRecogniser is UIPanGestureRecogniser || gestureRecogniser is UITapGestureRecogniser) && (otherGestureRecognizer is UIPanGestureRecogniser || otherGestureRecognizer is UITapGestureRecogniser) 
    }
    

    Note: Ensure your class conforms to the UIGestureRecogniserDelegate protocol and you set the gestures delegate so self.

    This should work, but I am unable to fully test it right now.

    UPDATE:

    If you are trying to recognise a tap during an animation you will likely need to use the UIViewAnimationOptions.AllowUserInteraction option in the options of UIView.animateWithDuration. Used this other answer as a source