Cancel UIGesture that already started iOS - ios

What I currently have:
I have a child UIViewController inside my main UIViewController. In this child UIViewController I have an UITableView, although anything can be inside of it (UIScrollView, UIImageView, composition of different UIViews sub-classes).
On my main UIViewController I have GestureRecognizerDelegate, so I am receiving callbacks when a gesture is made, like this:
- (void)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer movedWithTouches:(NSSet*)touches andEvent:(UIEvent *)event;
- (void)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer endWithTouches:(NSSet*)touches andEvent:(UIEvent *)event;
#optional
- (void)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer beganWithTouches:(NSSet*)touches andEvent:(UIEvent *)event;
For a particular gesture done on top of the main UIViewController, I am showing a small UIView with an UIImageView. So basically when a touch is made from top to botton where the Y < 100 the UIView animates and shows the image and when I release my finger from the screen the UIView goes back to the top. It's pretty much like the notification center that Apple provides, except that I don't control the scrolling of it and it only shows for 200px from the top.
The problem:
In theory the UIView with the UIImage is the top-est UIView on my hierarchy, but when I keep moving around with my finger on it's area, I can see the UITableView underneath it, moving. For me it doesn't make sense since the UIView with the UIImageView should be capturing those gestures.
What I want:
Simply when I show the UIView with the UIImage disable all the interaction on that childViewController.
What I have tried:
Currently I have this:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
If I put to NO, the UIView with the UIImage doesn't even show.
If I put something like myChildViewController.view.userInteractionEnabled = NO, since the gesture already started, it won't work. Of course if I use that before the gesture has started everything will work as intended. But the problem is that I won't be able to use the UITableView.

Well, in the end what's working is:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// Check if I am not on the Default state (UIView with the UIImageView hidden)
if(currentState != kDefaultState)
{
otherGestureRecognizer.enabled = NO;
[arrayOfDisabledGestures addObject:otherGestureRecognizer];
}
return YES;
}
When I finally close the UIView with the UIImageView I do the following:
[arrayOfDisabledGestures makeObjectsPerformSelector:#selector(setEnabled:) withObject:#YES];
To re-enabled all the gestures. I don't really like the solution, I think there should be (and I bet there are) other ways of doing this.

Related

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;
}

Enabling touch event on Objects In a UIScrollview

I've a scrollview that has a UIView on it and on those Views, there's a UIImageView on it, three UILabel on it, I want to enable user Interaction on it, but wouldn't work. I've enabled setUserInteraction for both the UIView, UIScrollView, UILabels, UIImageView none is Responding to click actions at all. The layout look like the Image Below....
implement
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
so the gestures of the uiscroll view won't conflict with the subview's recognisers
basically what happens is that the UIScrollView won't pass the events to its subviews because the default of the above method is to return NO
This sounds too easy to be the problem, but I've made the following mistake: Everything is set just right, but I did not drag out one of the SentEvents like TouchUpInside to an action in the implementation.
check this way,
1> first check whether your view controller respond to UIGestureRecognizerDelegate this way
#interface RootViewController : UIViewController<UIGestureRecognizerDelegate>
2> then in design check you map scrollview property and delegate properly
3> apply this code in viewDidload
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapditected)];
tapGesture.delegate = self;
// prevents the scroll view from swallowing up the touch event of child buttons
tapGesture.cancelsTouchesInView = NO;
[self.scroller addGestureRecognizer:tapGesture];
4> check you apply this code
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
5> if all goes wll then this method should detected
-(void)tapditected{
}

iOS - prevent click on UIButton from propagating to views behind it

I have a button on top of a GLKView.
When i click on the button, i also receive a long touch notification on the GLKView that is behind the button.
How can i prevent the notification from propagating to the view?
Found the solution to my question. The following code will do the trick:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
UIView* viewRceivingTouch = touch.view;
return (viewRceivingTouch == self.glkView);
}

iOS gesture collisions between slider and pan gesture on controller

I am using ECSlidingViewController for hamburger menu and I added code to my viewDidLoad method:
[self.slidingViewController.topViewController.view addGestureRecognizer:self.slidingViewController.panGesture];
Now I have pan gesture to show right menu or to hide. It's okay. But I have on view slider and it's really hard to get him working. I must tap on exact position. Is it possible to set that in exact rectangle (in view that contains slider) the slider would be answering on gesture and on other parts it would be working as now?
And one more question. When I have navigation controller with table and then I went on detail and then I show right menu it's okay but when I want to close it by pan I first go back in navigation and then close menu. Is it possible to change this order?
Have you tried setting UIGestureRecognizerDelegate and handling the both gesture recognizes in similar fashion as described in FAO?
e.g.:
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([otherGestureRecognizer.view isKindOfClass:[UISlider class]]) {
return YES;
} else {
return NO;
}
}

enable swipe on view controller, but disable within a view in that VC

I have a UIViewController where I have 2 UISwipeGestureRecognizers handling undo and redo (swipe right to undo, swiple left to redo). Within this VC I also have a UIView that is tracking touch began/moved/ended to change colors on another UIView. BTW, the undo/redo has to do with the color changes.
The problem I'm running into is that when I'm doing the touch events in the color changer view, they are sometimes interpreted as a swipe and undo/redo are happening.
How can I disable the swipe gestures just for the UIView in question but retain the ability to perform swipes on other areas of the VC?
Make the view controller a delegate of the gesture recognizer, then implement this delegate method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return touch.view != self.mySubviewToExclude;
}

Resources