UINavigationBar Touch

None of the other answers worked well for me. Rather than add a gesture to an existing subview of the navigationBar, or replace the titleView, I simply added a clear UIView covering a good portion of the navigationBar...

- (void) setupNavbarGestureRecognizer {
    // recognise taps on navigation bar to hide
    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showHideNavbar)];
    gestureRecognizer.numberOfTapsRequired = 1;
    // create a view which covers most of the tap bar to
    // manage the gestures - if we use the navigation bar
    // it interferes with the nav buttons
    CGRect frame = CGRectMake(self.view.frame.size.width/4, 0, self.view.frame.size.width/2, 44);
    UIView *navBarTapView = [[UIView alloc] initWithFrame:frame];
    [self.navigationController.navigationBar addSubview:navBarTapView];
    navBarTapView.backgroundColor = [UIColor clearColor];
    [navBarTapView setUserInteractionEnabled:YES];
    [navBarTapView addGestureRecognizer:gestureRecognizer];
}

You can add a gesture recognizer to be a single tap to the title of the navigation controller. I found that in the navigationBar subviews, the title is the one at index 1, the left button's index is 0 and the right button's index is 2.

UITapGestureRecognizer *navSingleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(navSingleTap)];
navSingleTap.numberOfTapsRequired = 1;
[[self.navigationController.navigationBar.subviews objectAtIndex:1] setUserInteractionEnabled:YES];
[[self.navigationController.navigationBar.subviews objectAtIndex:1] addGestureRecognizer:navSingleTap];

and then implement the following somewhere in your implementation.

-(void)navSingleTap

So you can use this for a single tap, or you can implement any gesture recognizer you want on that title.


The UINavigationItem class reference has a titleView property, which you can set to your custom UIView.

In other words, make a subclass of UIView with your touch handlers, and then when you push your navigation item, set that item's titleView property to an instance of your subclass.


The solution I found is a button, I use the following (but I don't know how "legal" it is):

UIButton *titleLabelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[titleLabelButton setTitle:@"myTitle" forState:UIControlStateNormal];
titleLabelButton.frame = CGRectMake(0, 0, 70, 44);
titleLabelButton.font = [UIFont boldSystemFontOfSize:16];
[titleLabelButton addTarget:self action:@selector(didTapTitleView:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.titleView = titleLabelButton;

Put that bit of code where ever you set your title. Then elsewhere I had this to test:

- (IBAction)didTapTitleView:(id) sender
{
    NSLog(@"Title tap");
}

which logged "Title tap" on the console!

The way I've gone about this may be completely wrong, but might give you an idea on what you can look in to. It's certainly helped me out! There's probably a better way of doing it though.