iosautolayoutuinavigationbaruisearchbarlayout-anchor

Centering a custom navigation bar item using layout anchors


I have created a custom navigation item (with both title and a UISearchBar) to replace the standard navigation title on iOS and I am trying to center it in a UINavigationBar using layout anchors.

However, the layout constraint [self.navigationItem.titleView.centerXAnchor constraintEqualToAnchor:self.navigationController.navigationBar.centerXAnchor].active = YES; does not work and the UIView containing the search bar shows up on the left side of the UINavigationBar.

Other constraints:

How to center the navigation bar item?

ScreenViewController.m:

- (void) viewDidLoad {
    [super viewDidLoad];

    // Create the search bar
    self.searchBar = [SearchBar new];

    // Create a new UIView as titleView (otherwise I'm receiving an error)   
    self.navigationItem.titleView = [UIView new];

    // Add into view hierarchy and turn off auto constraints
    [self.navigationController.navigationBar addSubview:self.navigationItem.titleView];
    [self.navigationItem.titleView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.navigationItem.titleView addSubview:self.searchBar.view];            
    [self.searchBar.view setTranslatesAutoresizingMaskIntoConstraints:NO];

    // Set anchors for the wrapping view
    [self.navigationItem.titleView.widthAnchor constraintEqualToAnchor:self.navigationController.navigationBar.widthAnchor multiplier:1.0/3.0].active = YES;
    //[self.navigationItem.titleView.heightAnchor constraintEqualToConstant:50.0].active = YES;
    [self.navigationItem.titleView.topAnchor constraintEqualToAnchor:self.navigationController.navigationBar.topAnchor].active = YES;
    [self.navigationItem.titleView.centerXAnchor constraintEqualToAnchor:self.navigationController.navigationBar.centerXAnchor].active = YES;
    [self.navigationItem.titleView.bottomAnchor constraintEqualToAnchor:self.navigationController.navigationBar.bottomAnchor].active = YES;

    // Set anchors for the search bar
    [self.searchBar.view.widthAnchor constraintEqualToAnchor:self.navigationItem.titleView.widthAnchor multiplier:1.0].active = YES;
    //[self.navigationItem.titleView.heightAnchor constraintEqualToConstant:50.0].active = YES;
    [self.searchBar.view.topAnchor constraintEqualToAnchor:self.navigationItem.titleView.topAnchor].active = YES;
    [self.searchBar.view.bottomAnchor constraintEqualToAnchor:self.navigationItem.titleView.bottomAnchor].active = YES;
    //[self.searchBar.view.leftAnchor constraintEqualToAnchor:self.navigationItem.titleView.leftAnchor].active = YES;
    //[self.searchBar.view.rightAnchor constraintEqualToAnchor:self.navigationItem.titleView.rightAnchor].active = YES;
    [self.searchBar.view.centerXAnchor constraintEqualToAnchor:self.navigationItem.titleView.centerXAnchor].active = YES;
}

Expected result: Centering search bar

What I get (the title view is not centered): Centering search bar problem

View hierarchy:

View hierarchy


Solution

  • Here is my solution, changing only the title view, setting its width anchor to a fraction of the navigation bar's to make it responsive:

    // Create search bar and set it as title view
    self.searchBar = [SearchBar new];
    self.navigationItem.titleView = self.searchBar.view;
    
    // Turn auto constraints off
    [self.searchBar.view setTranslatesAutoresizingMaskIntoConstraints:NO];
    
    // Set the layout anchors
    [self.navigationItem.titleView.widthAnchor constraintEqualToConstant:250.0].active = YES; // Had to set the width to a constant
    // Was still causing problems
    //[self.navigationItem.titleView.widthAnchor constraintEqualToAnchor:self.navigationController.navigationBar.widthAnchor multiplier:1.0/3.0].active = YES;// Still need to access the navigation bar's anchor
    [self.navigationItem.titleView.heightAnchor constraintEqualToConstant:50.0].active = YES;