How to use pan gesture and a swipe gesture alternatively on the same view?

AziCode picture AziCode · Nov 10, 2015 · Viewed 8.8k times · Source

I have a view that contains a counter.

I have implemented two different gesture recognizers,

a UISwipeGesture to increase the count by one,

and a UIPanGesture in order to increase the count by multiple numbers every

time the user swipes up.

Both gestures work, but my problem is they don't work at the same time.

I want them to work alternatively, for example if I do small swipes the

counter should increase by one, and if I keep dragging upwards the counter

should increase by multiple numbers.

Here's part of my code:

```

override func viewDidLoad() {
    super.viewDidLoad()

    setupSwipeGestures()
    setupPanGestures()
} 

private func setupSwipeGestures() {
    let swipeUp = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
    let swipeDown = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))

    swipeUp.direction = .Up
    swipeDown.direction = .Down

    circleView.addGestureRecognizer(swipeUp)
    circleView.addGestureRecognizer(swipeDown)
}


private func setupPanGestures() {
    let panGesture = UIPanGestureRecognizer(target: self, action: Selector("handleThePan:"))
    circleView.addGestureRecognizer(panGesture)
}



extension UIPanGestureRecognizer {
    func isDown(circleView: UIView) -> Bool {
       let velocity : CGPoint = velocityInView(circleView)
         if velocity.y < 0 {
            print("ex Gesture went up")
            return false
         } else {
            print("ex Gesture went down")
            return true
         }
     }
 }

```

P.S: The methods "handleSwipe" and "handlePan" contain the logic of the counter.

Answer

Craig Siemens picture Craig Siemens · Nov 10, 2015

A swipe and a pan gesture can not be recognized at the same time because a swipe gesture is just a special type of pan that has to be faster, short lived, and in one direction.

What you should do is setup the pan gestures to require the swipe gesture to fail before they can start. You will need to set each of the UISwipeGestureRecognizer to be a requireGestureRecognizerToFail on the UIPanGestureRecognizer

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeGestures = setupSwipeGestures()
    setupPanGestures(swipeGestures: swipeGestures)
} 

private func setupSwipeGestures() -> [UISwipeGestureRecognizer] {
    let swipeUp = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
    let swipeDown = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))

    swipeUp.direction = .Up
    swipeDown.direction = .Down

    circleView.addGestureRecognizer(swipeUp)
    circleView.addGestureRecognizer(swipeDown)

    return [swipeUp, swipeDown]
}

private func setupPanGestures(swipeGestures: [UISwipeGestureRecognizer]) {
    let panGesture = UIPanGestureRecognizer(target: self, action: Selector("handleThePan:"))
    for swipeGeature in swipeGestures {
        panGesture.requireGestureRecognizerToFail(swipeGesture)
    }
    circleView.addGestureRecognizer(panGesture)
}

Swift 3

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeGestures = setupSwipeGestures()
    setupPanGestures(swipeGestures: swipeGestures)
}

private func setupSwipeGestures() -> [UISwipeGestureRecognizer] {
    let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(self.handleSwipes))
    let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(self.handleSwipes))

    swipeUp.direction = .up
    swipeDown.direction = .down

    circleView.addGestureRecognizer(swipeUp)
    circleView.addGestureRecognizer(swipeDown)

    return [swipeUp, swipeDown]
}

private func setupPanGestures(swipeGestures: [UISwipeGestureRecognizer]) {
    let panGesture = UIPanGestureRecognizer.init(target: self, action:#selector(self.handleThePanUp))
    for swipeGesture in swipeGestures {
        panGesture.require(toFail: swipeGesture)
    }
    circleView.addGestureRecognizer(panGesture)
}