11

I have set up some gesture recognition in an app that I'm building. One of the gestures is a single finger single tap, which hides the toolbar at the top of the screen. Works great except for one thing: a tap on a link causes the toolbar to go away, too.

Is it possible to detect a tap that was not a tap on a link? Could I do this by seeing where the tap occurred, and only take action if it didn't occur on an html link? Is this is possible, a pointer to how to determine if a link was tapped would be helpful.

Per Octys suggestion, I did attempt to wrap the UIWebView inside a UIView. I'm using interface builder, so I inserted a view in the hierarchy, and made the UIWebView a "child" of the new UIView. The hierarchy looks like this now:

Hierarchy screen shot

I added an IBOutlet for the view in my view controller, and linked it up in interface builder.

I changed the gesture recognizer setup to look like this:

UITapGestureRecognizer* singleTap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleSingleTap:)];
singleTap.numberOfTouchesRequired=1;
singleTap.delegate=self;
[self.UIWebViewContainer addGestureRecognizer:singleTap];
[singleTap release];

This code resides in viewDidLoad.

As before, the code correctly sees a single finger single tap, but a tap on a link in the UIWebView also causes the toolbar to go away. I only want the toolbar to go away if a link was NOT tapped.

Anyone have any suggestions?

Thank you.

Chris

Thanks Chris

Chris
  • 1,013
  • 1
  • 15
  • 35

6 Answers6

10

Try wrapping your UIWebView in a UIView container and set your gesture recognizers on the container view. Touch events that are not handled by the UIWebView will be passed up the view hierarchy and be intercepted by your container view, assuming it implements the appropriate handlers (and it is these handlers that should implement the code for hiding the toolbars...).

octy
  • 6,525
  • 1
  • 28
  • 38
  • I had high hopes for this, but the behavior is still the same. If I comment out shouldRecognizeSimultaneouslyWithGestureRecognizer: the tap is not passed along to the containing view. Thanks. – Chris Jun 17 '11 at 17:16
  • Did you try setting `exclusiveTouch = YES` on your UIWebView? Not sure that'll work, but I can't think of anything else that makes sense right now... sorry! The thing with gesture recognizers is that they don't participate in the event delivery chain. So if this doesn't work, we have to come up with more elaborate solution. – octy Jun 17 '11 at 19:03
  • yup. Exclusivetouch didn't work, either. I'm wondering if UIWebView graps all single touch single finger taps because at the time of the event it doesn't know if the user has touched anything meaningful. – Chris Jun 17 '11 at 19:48
  • 1
    @octy - I'm having the same issue as yourself, however, the answer to this question doesn't fix the problem (as you stated). Did you figure out how to remedy this? – 5StringRyan Dec 13 '11 at 00:17
  • @5StringRyan: Most likely you did not set the delegate properly. – user523234 Nov 02 '12 at 22:15
  • In my case I placed a UIView as a sibling, and on top of, the UIWebView. – aceofspades Apr 28 '13 at 14:19
  • am also facing the same problem and cant find any solution so Chris and 5StringRyan how you do this please share with us – Anurag Soni May 31 '13 at 08:48
  • But why is this answer market as correct and so upvoted? Is it really working for someone? Not working here! – cprcrack Oct 24 '13 at 01:17
  • I had the same issue. After adding the "GESTURE.delegate = self" it works. For me it was a bit strange that it required the delegation – Vinh Feb 27 '14 at 16:51
3

OK, so one "hack-ish" workaround is to make the view controller which houses the UIWebView a delegate of the gesture recognizer that you instantiate(UIGestureRecognizerDelegate) I am usually not a fan of solutions like this one, but...

Assign the gesture recognizer to the view that wraps you web view, and set it's delegate to self.

then in the delegate method gestureRecognizer:shouldRecieveTouch method, set the state to indicate the there was a tap event,

Return NO from the delegate method so the event propagates down the responder chain to the UIWebView.

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{

    _userTapped = YES;
    [self performSelectorOnMainThread:@selector(hideMenuIfNotLink) afterDelay:??.?];
//??.?? amount of time to lapse to see if shouldStartLoadWithRequest gets called.
   return NO;

}

-(void)hideMenuIfNotLink{
    if(_userTapped)
         //hideMenu
}

Now, in your UIWebViewDelegate shouldStartLoadWithRequest (which gets called when a user has in fact clicked a link)

if(_userTapped){
    _userTapped = NO;
     //possibly code to reshow or verify keep showing menu
}
MAX308
  • 31
  • 1
1

This worked for me.try adding the below line of code

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Baby Groot
  • 4,637
  • 39
  • 52
  • 71
user578386
  • 1,061
  • 3
  • 14
  • 37
1

You can use the UIWebViewDelegate protocol's -webView:​shouldStartLoadWithRequest:​navigationType: method.

If the navigationType is UIWebViewNavigationTypeLinkClicked, you can get the URL for the click by checking [request URL].

Alexsander Akers
  • 15,967
  • 12
  • 58
  • 83
  • Yup, I am doing that. Maybe I didn't ask the question the right way. What I want to get to is this: I want to detect taps on a uiwebview that were NOT taps on a link. I want to use those taps to hide the toolbar. If a user taps on a link, I do NOT want to hide the toolbar. -- Thanks – Chris Jun 16 '11 at 19:45
1

I've been looking for the same thing and found this: There is an iOS specific property that disables the callout when you hold your finger on a link. You add this into the styling (CSS) of your urls.

-webkit-touch-callout: none;
Kheldar
  • 5,361
  • 3
  • 34
  • 63
0

I was having the same problem. This solution worked for me:

1) make sure to add the protocol to your interface: UIGestureRecognizerDelegate for example:

@interface ViewController : UIViewController _SlideViewProtocol, UIGestureRecognizerDelegate_

2) add this line of code

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
}

3)

UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(nextSlide)];
        swipeGesture.numberOfTouchesRequired = 1;
        swipeGesture.direction = (UISwipeGestureRecognizerDirectionLeft);
        swipeGesture.cancelsTouchesInView = YES;
        [swipeGesture setDelegate:self];
        [self.view addGestureRecognizer:swipeGesture];
Justin Mathews
  • 512
  • 4
  • 18
chrisallick
  • 1,330
  • 17
  • 18