Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to block a gesture from superview to subview?

I'm writing a module that everytime I swipe on a view, two sub views with a half size of the view will be added. Those subviews have their own gestures (eg: pan,...). The first time I swipe, it's OK because none of subview has been created. But once the subview been created, everytime I swipe, the swipe gesture is alway pass to its subviews. :(, so I have to swipe 2 times to divide.

I want to know is there any way to block swipe passing to its subview? Thank you.

UPDATE
I used shouldRecognizeSimultaneouslyWithGestureRecognizer to make those gestures work simultaneously. But there's still have some problems. The parent view have its Swipe gesture, the subview have its Pan gesture. Since I use souldRecognizeSimultaneouslyWithGestureRecognizer, sometime when I'm panning, the swipe gesture triggers. So, you know how to disable Swipe while Pan is active in this situation?

like image 454
Quang L. Avatar asked Jun 07 '13 08:06

Quang L.


3 Answers

You have to implement the UIGestureRecognizerDelegate method:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

And add your controller as the delegate of the gesture recognizers. Then, when two gesture recognizers respond to a gesture, this method will be called and here you can implement the logic you want for your app.

In the interface declaration of the controller you have to type:

@interface testcViewController () <UIGestureRecognizerDelegate>

Then, when creating the gesture recognizer:

UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
swipe.direction = UISwipeGestureRecognizerDirectionDown;
swipe.delegate = self;
[self.view addGestureRecognizer:swipe];

And then, finally, you add this method to the controller:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    BOOL shouldInteract = NO;
    //Here you decide whether or not the two recognizers whould interact.
    return shouldInteract;
}

EDIT You can also implement

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

And here, detect if you have already presented the subviews, and block any gesture you want.

like image 70
The dude Avatar answered Nov 10 '22 19:11

The dude


To block all gesture recognizers from superviews I created a UIGestureRecognizer sub class that will do just that when attached to a view. See the following code (taken from my WEPopover project):

#import "WEBlockingGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>

@implementation WEBlockingGestureRecognizer

- (id)init {
    return [self initWithTarget:self action:@selector(__dummyAction)];
}

- (id)initWithTarget:(id)target action:(SEL)action {
    if ((self = [super initWithTarget:target action:action])) {
        self.cancelsTouchesInView = NO;
    }
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    if (self.state == UIGestureRecognizerStatePossible) {
        self.state = UIGestureRecognizerStateBegan;
    }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    self.state = UIGestureRecognizerStateRecognized;
}

- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer {
    return [self isGestureRecognizerAllowed:preventingGestureRecognizer];
}

- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer {
    return ![self isGestureRecognizerAllowed:preventedGestureRecognizer];
}

- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return ![self isGestureRecognizerAllowed:otherGestureRecognizer];
}

- (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return NO;
}

- (BOOL)isGestureRecognizerAllowed:(UIGestureRecognizer *)gr {
    return [gr.view isDescendantOfView:self.view];
}

- (void)__dummyAction {

}

@end

If you want to block all gesture recognizers attached to parent views of some view, just do the following:

- (void)blockParentGesturesForView:(UIView *)v {
    [v addGestureRecognizer:[WEBlockingGestureRecognizer new]];
}
like image 22
Werner Altewischer Avatar answered Nov 10 '22 17:11

Werner Altewischer


set userinteractionEnabled to NO of your subView

 subview.userinteractionEnabled=NO

if you dont want to disable userInteraction then use cancelsTouchesInView method

cancelsTouchesInView—If a gesture recognizer recognizes its gesture, it unbinds the remaining touches of that gesture from their view (so the window won’t deliver them). The window cancels the previously delivered touches with a (touchesCancelled:withEvent:) message. If a gesture recognizer doesn’t recognize its gesture, the view receives all touches in the multi-touch sequence.

like image 2
Ravindra Bagale Avatar answered Nov 10 '22 17:11

Ravindra Bagale