How to block a gesture from superview to subview?
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.
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.
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]];
}