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

1

6

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.

Commodore answered 10/11, 2015 at 18:43 Comment(2)
If you want a gesture recognizer to kick in only if the other fails, you could use the requireGestureRecognizerToFail method. However, in your case, it seems like the two gesture recognizers would conflict. So you might consider just using a single gesture recognizer, then querying the velocity over time to see if the user is continuing to drag.Naima
I posted an answer on this SO question that demonstrates how to give priority to swipe or use pan for everything.Mamiemamma
Y
15

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)
}
Yunyunfei answered 10/11, 2015 at 19:1 Comment(4)
Thanks for the tip . I have another Tap gesture that i use just once in order to increase the size of the view. Do you think it will conflict with the UISwipeGesture and the UIPanGesture ? Can I setup the speed of the pan so that it increases the counter in a slowly manner ?Commodore
Tap shouldn't interfere. You could set it up so the counter is increased when you pan x points so as you pan, it can increase more than once.Yunyunfei
Should I set up the speed in the extension of the UIPanGesture ?Commodore
You would handle that in handleThePan: by checking for how far the pan has moved and updating your counter the appropriate amount.Yunyunfei

© 2022 - 2024 — McMap. All rights reserved.