Handling Multiple Gesturerecognizers

Handling Multiple GestureRecognizers

The UIGestureRecognizerDelegate has a special function managing simultaneous recognition of several gestures on the same object, that will do the trick.

1) Set your UIViewController to conform UIGestureRecognizerDelegate

2) Implement the following function:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {

if (gestureRecognizer == mainScene.panRecognizer || gestureRecognizer == mainScene.pinchRecognizer) && otherGestureRecognizer == mainScene.tapRecognizer {
return true
}
return false
}

In this particular example we allow the tap gesture to get triggered simultaneously with panning and pinching.

3) Then just assign the delegates to the pan and pinch gesture recognizers:

override func viewDidLoad() {
// your code...

// Set gesture recognizers delegates
mainScene.panRecognizer.delegate = self
mainScene.pinchRecognizer.delegate = self
}

Objective-C handling multiple gestures at once

Found my issue. I had the exclusiveTouch property on the view set to YES. When I removed that line of code, having both gesture recognizers together worked great!

How to disable one of multiple gesture recognizers?

You should assign the name property to your gesture recognizer.

tap.name = "myTapGesture"

And later you can cycle through the recozniers and only disable the one that you want.

for aRecognizer in view.gestureRecognizers {
if let name = aRecognizer.name {
if name == "myTapGesture" {
aRecognizer.isEnabled = false
}
}
}

Adding Multiple UITapGestureRecognizers to single view (Cocos2d)

You can add multiple gesture recognizers to the same view. What you can't (easily) do is add multiple instances of the same gesture recognizer type (pan, swipe, double-tap, etc) to the same view.

Why?

Because as soon as the first gesture recognizer recognizes the gesture (double tap in this case) it cancels all touch events. Therefore the remaining gesture recognizers will never finish recognition, and will never fire their events.

You do not need more than one gesture recognizer of the same type. In your case, once you've received the double-tap event, it's up to you to signal the right object that it was double-tapped. Use the recognizer's position and other attributes to find, for example, the sprite that was double-tapped and then have it do whatever it needs to do.

For that reason it's good design to let the gestures be recognized by a higher-level node in your scene hierarchy (ie the UI layer) which then passes on the events to the appropriate nodes, or simply ignores it.

Can you attach a UIGestureRecognizer to multiple views?

A UIGestureRecognizer is to be used with a single view. I agree the documentation is spotty. That UIGestureRecognizer has a single view property gives it away:

view

The view the gesture recognizer is attached to. (read-only)

@property(nonatomic, readonly) UIView *view

Discussion You attach (or add) a gesture recognizer to a UIView object
using the addGestureRecognizer:
method.

Handling UIPanGestureRecognizer gestures for multiple Views (one covers the other)

Managed to get this working.

Of the methods described in my question above I removed the top one keeping just this (it has a few changes):

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if ((gestureRecognizer as! UIPanGestureRecognizer).velocityInView(view).y < 0
|| pulloverVC.tableView.contentOffset.y > 0)
&& pulloverVC.view.frame.origin.y == bottomNavbarY {
return true // enable tableview control
}
return false
}

The if statement checks that the covering UITableView is in its upper position AND that either the user is is not dragging downwards or the table content is offset (we are not at the top of the table). If this is true, then we return true to enable the tableview.

After this method is called, the standard method implemented to handle my pan gesture is called. In here I have an if statement that sort of checks the opposite to above, and if that's true, it prevents control over the covering viewB from moving:

func handlePanGesture(recognizer: UIPanGestureRecognizer) {

let gestureIsDraggingFromTopToBottom = (recognizer.velocityInView(view).y > 0)

if pulloverVC.view.frame.origin.y != bottomNavbarY || (pulloverVC.view.frame.origin.y == bottomNavbarY && gestureIsDraggingFromTopToBottom && pulloverVC.tableView.contentOffset.y == 0) {

...

This now keeps the UITableView interaction off unless its parent view viewB is in the correct position, and when it is, disables the movement of viewB so that only interaction with the UITableView works.

Then when, we are at the top of the table, and drag downwards, interaction with the UITableView is re-disabled and interaction with its parent view viewB is re-enabled.

A wordy post and answer, but if someone can make sense of what I'm saying, hopefully it will help you.

iOS - Multiple Tap gesture recognizers

Check with this,

[oneTap requireGestureRecognizerToFail:doubleTap];
[oneTap requireGestureRecognizerToFail:tripleTap];
[doubleTap requireGestureRecognizerToFail:tripleTap];

You had switched the taps in the methods and you were not doing the second line above. Ideally one tap should be detected only when double tap and triple tap fails. And double tap should be detected when triple tap fails.

Two UIGestureRecognizer on one view?

You need to make your Game Scene view the delegate of your gesture recognizer. You will also need implement its method shouldRecognizeSimultaneouslyWith as mentioned by xmasRights:

So in your Game scene declaration just add UIGestureRecognizerDelegate:

class GameScene: SKScene, SKPhysicsContactDelegate, UIGestureRecognizerDelegate {

And in your didMove(to view: SKView) method make set its delegate:

let longPress = UILongPressGestureRecognizer()
longPress.delegate = self
longPress.minimumPressDuration = 0
longPress.addTarget(self, action: #selector(longPressGesture))
view.addGestureRecognizer(longPress)

let swipeUp = UISwipeGestureRecognizer()
swipeUp.delegate = self
swipeUp.direction = .up
swipeUp.addTarget(self, action: #selector(swipeUpGesture))
view.addGestureRecognizer(swipeUp)

Also In Swift 4 you will need to add @objc to your methods

@objc func longPressGesture(_ longPress: UILongPressGestureRecognizer) {
print("longPressGesture")
}

@objc func swipeUpGesture(_ swipeUp: UISwipeGestureRecognizer) {
print("swipeUpGesture")
}

Don't forget also to add the method shouldRecognizeSimultaneouslyWith as already mentioned by xmasRights:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
print("shouldRecognizeSimultaneouslyWith")
return true
}


Related Topics



Leave a reply



Submit