Uitapgesturerecognizer Tap on Self.View But Ignore Subviews

UITapGestureRecognizer tap on self.view but ignore subviews

You should adopt the UIGestureRecognizerDelegate protocol inside the self object and call the below method for checking the view. Inside this method, check your view against touch.view and return the appropriate bool (Yes/No). Something like this:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isDescendantOfView:yourSubView]) {
return NO;
}
return YES;
}

Edit: Please, also check @Ian's answer!

Swift 5

// MARK: UIGestureRecognizerDelegate methods, You need to set the delegate of the recognizer
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if touch.view?.isDescendant(of: tableView) == true {
return false
}
return true
}

Exclude subviews from UIGestureRecognizer

iOS 6 introduces a great new feature that solves this exact problem - a UIView (subview) can return NO from gestureRecognizerShouldBegin: (gesture recognizer attached to a superview). Indeed, that is the default for some UIView subclasses with regard to some gesture recognizers already (e.g. a UIButton with regard to a UITapGestureRecognizer attached to a superview).

See my book on this topic: http://www.apeth.com/iOSBook/ch18.html#_gesture_recognizers

How do I prevent taps on a subview from triggering a UITapGestureRecognizer on a parent view?

Add subview to the background of the view, and attach tap gesture recogniser to the subview:

UIView* subview = [[UIView alloc] initWithFrame:view.bounds];
subview.backgroundColor = [UIColor clearColor];//or view.backgroundColor
[view addSubview:subview];
[view sendSubviewToBack:subview];
[subview addGestureRecognizer:tapRecognizer];

exclude subview from UITapGestureRecognizer

You can use gesture recognizer delegate to limit area where it can recognise touches similar to this example:

recognizer.delegate = self;
...

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
CGPoint touchPoint = [touch locationInView:superview];
return !CGRectContainsPoint(subview.frame, touchPoint);
}

Note that you need to keep reference to your parent and child view (make them instance variables?) to be able to use them in delegate method

UITapGestureRecognizer seems not blocked by its subviews, is that normal?

The reason the subView is not blocking is because it is not consuming the touch event.

If a view receives a touch event but doesn’t consume it the that event gets passed up the view hierarchy all the way back to the OS lying behind your app.

If you don’t want your tap gesture recogniser to receive touches inside your image view then you can just turn on isUserInteractionEnabled on the image view.

This will then make the image view consume the touch event and the gesture recogniser won’t receive it.

How to Exclude gesture for subview?

You can ignore the swipe gesture for particular area using following method.

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool

and still you can call touchesMoved to draw your signature. Here is the sample code.

func addSwipeGesture() {
let leftSwipe = UISwipeGestureRecognizer(target: self, action:
#selector(handleSwipes(_:)))
leftSwipe.delegate = self
let rightSwipe = UISwipeGestureRecognizer(target: self, action:
#selector(handleSwipes(_:)))
rightSwipe.delegate = self

leftSwipe.direction = .left
rightSwipe.direction = .right

self.view.addGestureRecognizer(leftSwipe)
self.view.addGestureRecognizer(rightSwipe)
}

@objc func handleSwipes(_ sender:UISwipeGestureRecognizer) {

if (sender.direction == .left) {
print("Swipe Left")
}

if (sender.direction == .right) {
print("Swipe Right")
}
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive
touch: UITouch) -> Bool {
return !self.imgView.bounds.contains(touch.location(in: self.imgView))
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
print("moving")
}

For the above code snippet, swipe will get ignored for image view i.e. imgView

UIGestureRecognizer blocks subview for handling touch events

I had a very similar problem and found my solution in this SO question. In summary, set yourself as the delegate for your UIGestureRecognizer and then check the targeted view before allowing your recognizer to process the touch. The relevant delegate method is:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch

UITapGestureRecognizer on UIView and Its Subview Respond Together When Subview Is Tapped

Try the following code:

conform the <UIGestureRecognizerDelegate> to your class.

set yourGesture.delegate = self;

then add this delegate Method:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// return YES (the default) to allow the gesture recognizer to examine the touch object, NO to prevent the gesture recognizer from seeing this touch object.
if([touch.view isKindOfClass: [UITextView class]] == YES)] {
return YES;
}
else {
return NO;
}
}

Hope it will solve your issue. Enjoy Coding..!!!!

Avoid Passing Touch Event to the Background View Behind

Because the stack view is a sub-view of View and not added over the top (like a presented view controller), its going to receive the touch events like you're experiencing. Your view controller needs to adopt the UIGestureRecognizerDelegate protocol, then you need to set the gesture's delegate to the view controller (most likely you just need to set it to "self") and then implement the following function:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
//the below will return false if the touch's view is not the gesture recognizer's view
return touch.view == gestureRecognizer.view
}

The code example was referenced from: UITapGestureRecognizer tap on self.view but ignore subviews



Related Topics



Leave a reply



Submit