separate tap gesture recognizers in uitableview header - ios

Is there a simple solution to adding multiple UITapGestureRecognizers? I have a table view header which contains a UIImageView. Around the image view edges is clear space for the header. What I am trying to achieve is add a tap method for the header and tap method for the image view. But adding one to the header uses the entire header, including the image view. Is there a way to separate them?
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIView *header = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 250)];
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(35, 10, 250, 250)];
_imageView = imageView;
_imageView.image = imageData;
UITapGestureRecognizer *headerTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(headerTapped:)];
_headerTap = headerTap;
UITapGestureRecognizer *imagetap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(imageTapped:)];
_imagetap = imagetap;
[header addGestureRecognizer:_headerTap];
[_imageView addGestureRecognizer:_imagetap];
[header addSubview:_imageView];
return header;
}

Make a transparent button covering the entire header.
Put the image view above it and cover that with another transparent button.

You can accomplish this by listening to the delegate methods of the gesture recognizer. Depending on how your views are set up you can use
(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
to see decide if you want your recognizer to fire. For instance We have an app with a drop down tableview to perform selections. We installed a two recognizers, one on the window so we can 'roll up' the drop down when the user taps outside of it, and one on the 'button' which is just the contents of a cell. We use this method to determine if the touch was outside of our visible tableviews bounds an if so we dismiss it.
The other relevant delegate method is
(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
From your description this seems like the best to use. From this you can tell your headers gesture recognizer not to fire alongside the one on your image view. For example
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if (gestureRecognizer == self.headerGestureReconizer && otherGestureRecognizer == self.imageViewGestRecognizer) {
return NO;
}
return YES;
}
You can also set up dependencies within gesture recognizers via the instance method (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer. This is most useful when you have something like a single tap and a double tap recognizer on the same view and isn't what you want in this situation.

Related

UITapGesture for Button are working. But, long press gesture for the same are not working

I have a table view with X number of rows.
One of the row has collection view inside it.
Collection view has Y number of cells.
Every cell has a button.
Now, the problem is; If I apply a tap gesture for button inside the collection view cell it works.
But, when I apply a long press gesture to button it is not working at all.
Following is the code that I am trying.
-(void)setupGestureForAllButton{
for (UIButton *button in self.keyboardButtons) {
UILongPressGestureRecognizer *gr = [[UILongPressGestureRecognizer alloc] init];
[gr addTarget:self action:#selector(userLongPressed:)];
[button addGestureRecognizer:gr];
}
}
- (void)userLongPressed:(id)sender {
NSLog(#"user long pressed");
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Please find the pictorial representation of the problem
UPDATE 1 :
setting gr.delegate = self; did the trick.
I am still not sure; then, why it was working for tap gesture in the first place.

Gesture recognizor on UICollectionView not receiving gestures

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

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

UITableView backgroundView gestures on iOS 7?

I have a view controller subclass. I'm trying to connect a gesture recognizer to trap taps below the rows.
To do this, I have an empty row at the bottom, so the user can always scroll so there's an empty cell on the screen. I can trap taps on this row easily.
But Reminders on iOS 7 supports tapping even under that; if there's space for three more rows on the table, any of those three can be tapped not just the first one.
For example, you can tap in the red area:
To do this on iOS 6, I added a background view to the table and hooked a gesture recognizer to it:
UIView *backgroundView = [[UIView alloc] init];
[backgroundView addGestureRecognizer:_tapOutsideGesture];
backgroundView.backgroundColor = [UIColor clearColor];
self.tableView.backgroundView = backgroundView;
This works when on 6.1, but not 7.0. What am I missing?
I'm building with Xcode 5.0 and the 7.0 SDK, with IPHONEOS_DEPLOYMENT_TARGET = 6.1.
Add a gesture recognizer in your table view
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doSomething:)];
tapGesture.delegate = self;
[self.tableView addGestureRecognizer:tapGesture];
and check if the tap was over some cell.
#pragma mark – UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return ![self.tableView indexPathForRowAtPoint:[touch locationInView:self.tableView]];
}
You could try to use
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
of UIGestureRecognizerDelegate and check in which view you are, and if you are in table cell then return NO.
Off course there are some issues with iOS7.
If you would like to check if you are in UITableViewCell you have to call view.superview.superview in iOS7 and in iOS6 it was view.superview.
More info about iOS7:
How to get UITableView from UITableViewCell? https://devforums.apple.com/message/865550#865550

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