Gesture recognizor on UICollectionView not receiving gestures - ios

I have a ViewController with a vertically scrolling collection view that takes up the entire view. I want to be able to get swipe and pan gestures on the entire collection view (not just on cells) but I can't get any gestures. I have tried adding the gesture recognizer to the view and the collection view but neither seem to work.
Adding the gesture recognizer to the view
self.panEdgeGesture = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
self.panEdgeGesture.delegate = self;
[self.collectionView addGestureRecognizer:self.panEdgeGesture];
[self.panEdgeGesture setEdges:UIRectEdgeRight];
Then I added these functions:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch{
return YES;
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
- (void)handlePan:(UISwipeGestureRecognizer *)sender
{
DebugLog(#"Received pan gesture");
}
Could the collection view cells stop the gesture events from triggering? They have no gestures themselves.

Per UIScreenEdgePanGestureRecognizer's Class Reference:
After creating a screen edge pan gesture recognizer, assign an
appropriate value to the edges property before attaching the gesture
recognizer to your view. You use this property to specify from which
edges the gesture may start. This gesture recognizer ignores any
touches beyond the first touch.
So change you code to:
self.panEdgeGesture = [[UIScreenEdgePanGestureRecognizer alloc];
[self.panEdgeGesture setEdges:UIRectEdgeRight];
initWithTarget:self action:#selector(handlePan:)];
self.panEdgeGesture.delegate = self;
[self.collectionView addGestureRecognizer:self.panEdgeGesture];

Related

Table View selection and pan gesture

I have a table view with a pan gesture on it. When I start panning the tableview up and down the tableView selection gets disable and I can't select tableview cells.
UIPanGesture* tablePanGesture =[[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(gestureHandler:)];
tablePanGesture.delegate = self;
[tableView addGestureRecognizer:tablePanGesture];
[tablePanGesture setCancelsTouchesInView:NO];
And I using the following delegate to let my gestures and tableview gestures work together:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
I have implemented the method for table view didSelectRowAtIndexPath but when I use panning it is not called.
Is there any conflict between pan gesture and tableview Delegate?
You are missing this line:-
[tablePanGesture setCancelsTouchesInView:NO];
This will let the UIPanGesture recognize the pan gesture and also pass the touch to the next responder means your table view select or tap.

SWRevealViewController pan gesture recogniser issue

I am using SWRevealViewController from John-Lluch. I need to use pan gesture to view the sidebars and I am using swipe to view my previous and next articles. However, the pan gesture can only be detected.
UPDATED: My swipe gesture worked if I disable my pan gesture.
Pan Gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
Swipe gesture
UISwipeGestureRecognizer *left = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft:)] autorelease];
left.direction = UISwipeGestureRecognizerDirectionLeft;
UISwipeGestureRecognizer *right = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)] autorelease];
right.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:left];
[self.view addGestureRecognizer:right];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
[self.view addGestureRecognizer:left];
Notice the difference? Implement the SwipeGesture as a property in your .h or make it in your .xib and link it to your .h
It is difficult to handle both pan and swipe gesture recognizer simultaneously. You will have handle the SWRevealViewController delegates for pan gesture and also swipe gesture for the current viewcontroller.
As apple suggests to differentiate the gesture you could use the following method
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Excerpt from the Apple Documentation:
This method is called when recognition of a gesture by either
gestureRecognizer or otherGestureRecognizer would block the other
gesture recognizer from recognizing its gesture. Note that returning
YES is guaranteed to allow simultaneous recognition; returning NO, on
the other hand, is not guaranteed to prevent simultaneous recognition
because the other gesture recognizer's delegate may return YES.

How to receive touch event behind another view?

I have two subviews inside the view. The frame is equal. A view has a swipe left gesture recognizer and B view has a swipe right gesture recognizer. B is behind A so I can only trigger swipe left gesture. How can I receive both?
The view in the back will not respond because, well, it's in the back.
For both gestures to respond simultaneously (left+right at the same time), add a UIGestureRecognizerDelegate to either and handle shouldRecognizeSimultaneouslyWithGestureRecognizer as suggested below.
If you want B to respond to a gesture, even though it is partially hidden by A, rethink your hierarchy: add a 3rd view above A & B (call it C), same size as B, as a placeholder to your gesture recognizer.
Your delegate:
// leftGesture
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
*)otherGestureRecognizer
{
return otherGestureRecognizer == rightGesture;
}
How can I receive both?
Add both gesture recognizers to view A, since that's the view in front. Since you need the right swipe gesture to be handled by view B, make view B the target for the right swipe gesture recognizer.
A better option might be to make your view controller the target of both gesture recognizers and let it sort out what to do with the user's gestures. That helps to get the views out of the business of knowing how the user interface is set up -- they just have to follow instructions from the view controller. If you adopt that plan, your view controller might look like this in part:
- (void)viewDidLoad
{
UISwipeGestureController *leftSwipe = [[UISwipeGestureController alloc] initWithTarget:self action:#selector(leftSwipe:)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
UISwipeGestureController *rightSwipe = [[UISwipeGestureController alloc] initWithTarget:self action:#selector(rightSwipe:)];
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
[self.viewA addGestureRecognizer:leftSwipe];
[self.viewA addGestureRecognizer:rightSwipe];
}
- (IBAction)leftSwipe:(id)sender
{
[self.viewA doSomething];
}
- (IBAction)rightSwipe:(id)sender
{
[self.viewB doSomethingElse];
}

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.

uiwebview inside uipageviewcontroller blocks tap to turn page

I have a uiwebview inside the uipageviewcontroller, I want to be able to select some text in the view so I have userInteractionEnabled set to YES, but when I do that I loose the option of turning the page by tapping, although swiping still works fine.
What's the best way to trap the UITapReconizer on the UIWebview and pass it on to the UIPageviewController?
Thanks.
UIPageviewController has a gestureRecognizers property
My guess is that one if its gesture recognizer and yours - if your using one - can't act simultaneously.
You could handle that through the gestures' methods, see question for handling multiple UITapGestureRecognizers, requiring your webView tap recognizer to fail for pageViewController's tap to succeed.
Like this (not tested)
UILongPressGestureRecognizer *yourTapGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
for(UIGesture *gesture in yourPageController.gestureRecognizers){
[gesture requireGestureRecognizerToFail:yourTapGesture];
}
[pageControllerTap requireGestureRecognizerToFail:yourTapGesture];
Also, I don't understand why you need userInteractionEnabled, is your UIWebView taking all space ? You could attach the gesture to webView's superview, and test webView-hit with locationInView: method.
I've sorted it.
I've added a gesture recogniser to the controller generating the uiwebview:
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleGesture:)];
tapRecognizer.numberOfTapsRequired = 1;
tapRecognizer.delegate = self;
[webView addGestureRecognizer:tapRecognizer];
With
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return NO;
}
And adding in the pageviewController:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}

Resources