Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click events in UINavigationBar overridden by the gesture recognizer

The question in the first place was:

When you have a tableView how to implement that the user can tap the NavigationBar to scroll all the way to the top.

Solution:

- (void)viewDidLoad {
    UITapGestureRecognizer* tapRecon = [[UITapGestureRecognizer alloc]
              initWithTarget:self action:@selector(navigationBarDoubleTap:)];
    tapRecon.numberOfTapsRequired = 2;
    [navController.navigationBar addGestureRecognizer:tapRecon];
    [tapRecon release];
}

- (void)navigationBarDoubleTap:(UIGestureRecognizer*)recognizer {
    [tableView setContentOffset:CGPointMake(0,0) animated:YES];
}

Which works like a charm!

But Drarok pointed out an issue:

This approach is only viable if you don't have a back button, or rightBarButtonItem. Their click events are overridden by the gesture recognizer

My question:

How can I have the nice feature that my NavigationBar is clickable but still be able to use the back buttons in my app?

So either find a different solution that doesn't override the back button or find a solution to get the back button back to working again :)

like image 360
Octoshape Avatar asked Oct 14 '11 20:10

Octoshape


3 Answers

Rather than using location view, I solved this by checking the class of the UITouch.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return (![[[touch view] class] isSubclassOfClass:[UIControl class]]);
}

Note that the nav buttons are of type UINavigationButton which is not exposed, hence the subclass checking.

This method goes in the class you designate as the delegate of the gesture recognizer. If you're just getting started with gesture recognizers, note that the delegate is set separately from the target.

like image 88
Ben Flynn Avatar answered Nov 08 '22 04:11

Ben Flynn


UIGestureRecognizerDelegate has a method called "gestureRecognizer:shouldReceiveTouch". If you are able to point out if the touch's view is the button, just make it return "NO", otherwise return "YES" and you're good to go.

like image 7
Stavash Avatar answered Nov 08 '22 04:11

Stavash


UIGestureRecognizer also has an attribute @property(nonatomic) BOOL cancelsTouchesInView. From the documentation: A Boolean value affecting whether touches are delivered to a view when a gesture is recognized.

So if you simply do

tapRecon.cancelsTouchesInView = NO;

this might be an even simpler solution, depending on your use case. This is how I do it in my app.

When pressing a button in the navigation bar though, its action is executed (as desired), but the UIGestureRecognizer's action is executed as well. If that doesn't bother you, then that would be the simplest solution I could think of.

like image 5
Dennis Avatar answered Nov 08 '22 04:11

Dennis