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
Using JSONencoder to Encode a Variable with Codable as Type
Detect iOS Application About to Delete
Cannot Use Instance Member Within Property Initializer
Nsdata Won't Accept Valid Base64 Encoded String
How to Show Alertview with Activity Indicator
Simple Way to Change the Position of Uiview
Uitableview Dynamic Cell Heights Only Correct After Some Scrolling
Use Didselectrowatindexpath or Prepareforsegue Method for Uitableview
Xcode - There Are No Dsyms Available for Download
How to Make View the Size of Another View in Swiftui
How Could I Get an Array of Emojis Found in iOS8.3
Nscache Doesn't Work with All Images When Loading for the First Time
How to Show a Collectionview Like Facebook Upload Image Using Swift 4
Cannot Subscript a Value of Type '[Nsobject:Anyobject]' with an Index of Type 'String'
Swiftui - iOS 13 Uiviewrepresentable of Wkwebview Gets Thread 1: Exc_Breakpoint Crash
What Is Prefix.Pch File in Xcode
How to Use Apple's New .P8 Certificate for Apns in Firebase Console