gesture recognizer is not working on subview - ios

I have a UIView which has a UILabel view as a subview. Now I have added gesture for self (which is UIView). UIView recognizes the touch but subview(UILabel) doesn't.
There are similar questions in stackoverflow which tells the below property to set YES. I tried but it doesn't solve.
I have also set label.userInteractionEnabled = YES.

Try this
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UILabel class]])
{
return YES;
}
return YES;
}
You may need to set the delegate of gesture recognizer as self

Related

Are subviews automatically added as listeners to their superview's UIGestureRecognizers?

I have a swipe gesture attached to a UIView that doesn't seem to be registering when the swipe is on top of it's subviews.
One of solution is to check is gesture point inside your subview or not,
there is a useful C function:
/* Return true if `point' is contained in `rect', false otherwise. */
bool CGRectContainsPoint(CGRect rect, CGPoint point)
that you can use like this:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return CGRectContainsPoint(subview.frame, [touch locationInView:self.view]);;
}
The other solutions should work, but a potentially easier one is to set subview.userInteractionEnabled = false in the subview if it doesn't have its own event handlers.
Let's say A is the root UIView which you want to receive swipes, and B is a subview of A that you don't really want to receive swipes.
if you do not want to receive any gestures on B, you can userInteractionEnabled = false on it
if you still want to receive some gestures on B (but not a swipe)
you must subclass B so that you can implement this method, and implement this method in B
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([gestureRecognizer isKindOfClass:UISwipeGestureRecognizer]) {
return NO;
}
return YES;
}
You can also see how you may get a wide range of functionality from implementing gestureRecognizer:shouldReceiveTouch:

Adding a UIGestureRecognizer taking priority over all other interactions

When I tap on a UIButton, a UIView MyView appear from the bottom a cover a third of the screen. I would like that when I tap somewhere outside this view, it disappears.
I thought about adding another transparent UIView right under MyView and add a tab gesture on it with the dismiss function but I'm sure there is something cleaner than this.
So I thought about adding the tap gesture MyTapGesture to dismiss MyView on self.view of the UIViewController. The problem is that outside this view, I have other UIControls and gestures that capture also any touch at the same time than MyTapGesture.
How can I make MyTapGesture the priority gesture outside MyView and ignore all other gesture, taps, etc...?
You may have to use the gesture delegate methods to handle two tapGestureRecognizer activate the one you need depending on scenario
#pragma mark - UIGestureRecognizerDelegate methods
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([tapGestureRecognizer1 isEqual:gestureRecognizer]) {
return [tapGestureRecognizer2 isEqual:otherGestureRecognizer];
}
if ([tapGestureRecognizer2 isEqual:gestureRecognizer]) {
return [tapGestureRecognizer1 isEqual:otherGestureRecognizer];
}
return NO;
}

Touch Events on UIView on UITableView

I'm trying to catch the touchesBegan and the touchesMoved events on an UIView.
I have a UITableView; each cell contains a UIView with several controls. One of these controls is a subclass of a UIView with code in the touchesBegan and touchesMoved events.
If this control is not on the tableviewcell, then it works fine. But in this situation, all touches have effect to the tableview, but not to the UIView.
How to ignore the TouchEvents and redirect them to the UIView?
Try setting delaysContentTouches property of the tableview(scrollview) to YES.
Try this one..
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isDescendantOfView:yourview])
{
return NO;
}
return YES;
}

UIScrollView overrides my subview's pan gesture recognizers

If I have a scrollView with a subview and the subview has a pan gesture recognizer, the scrollView's pan gesture override's the subview's pan. What I want is the opposite, I think, so that is I drag a subview it will pan within the scroll view, yet if I touch another area the scroll view will pan as normal. Is there an easy way to set that up?
Here's what works for me:
UIPanGestureRecognizer *subviewPanRecognizer = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(panSubview:)];
[subview addGestureRecognizer:subviewPanRecognizer];
// play nice with subview's pan gesture
[scrollView.panGestureRecognizer
requireGestureRecognizerToFail:subviewPanRecognizer];
Set canCancelContentTouches property of UIScrollView to false if you don't want to scroll on touching subviews.
Original answer
Overwrite these two delegate below,
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
This will allow you to recognize both gestures, the default return is NO, so we need to overwrite it and return YES.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
return NO;
}else{
return YES;
}
}
return YES;
}
In this delegate you can do anything as you wish, as it's name the gestureRecoginzer will be required to fail by the otherGestureRecognizer, all you need to do is to judge what kind of these two gestures and return YES or NO.

Tap on UIBarButtonItem is not ignored by TapGestureRecognizer

I have a view with a UIToolbar with a few UIBarButtonItems and a UITableView containing some UITextFields.
I would like to dismiss the keyboard for a textfield with a tap anywhere. Therefore I added a TapGestureRecognizer to the view. To avoid that the TapgestureRecognizer handles taps on the UIBarButtonItems I added the following method (delegate is set).
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
UIView *view = touch.view;
while (view) {
NSLog(#"Class of view: %#", NSStringFromClass([view class]));
view = view.superview;
}
// Disallow recognition of tap gestures in the toolbar
if ([touch.view isKindOfClass:[UIToolbar class]]) {
return NO;
}
if ([touch.view.superview isMemberOfClass:[UIToolbar class]]) {
return NO;
}
return YES;
}
A UIBarButtonItem is not a view itself, but it has UIToolbar as its superview. When I use the above method, the check for isKindOfClass:[UIToolbar class] does not seem to work for all taps on the toolbar. However the check for the superview with isMemberOfClass:[UIToolbar class] works.
I don't understand this. Maybe someone can explain this behavior?
You shouldn't rely on the view hierarchy around private view classes. It could change at any time.
A better approach is to add the gesture to the table view (or other appropriate view which represents the area you're interested in). Just be sure to enable and disable the gesture at appropriate times so as not to block the usual table operation.

Resources