griz
griz

Reputation: 470

UISearchBar scope buttons in UINavigationBar/UINavigationItem

I am trying to add a UISearchBar to my UINavigationItem but the scope bar is showing behind the search bar. Any ideas to fix that problem?

iOS: 11.2 xCode: 9.2

my code:

- (void)viewDidLoad 
{
    [super viewDidLoad];

    self.mySearchBar = [[UISearchBar alloc] init];
    self.mySearchBar.delegate = self;
    self.mySearchBar.scopeButtonTitles = @[@"item 1", @"item 2", @"item 3"];
    self.navigationItem.titleView = self.mySearchBar;
}

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
    [self.mySearchBar setShowsScopeBar: TRUE];
    [self.mySearchBar setShowsCancelButton:TRUE animated:TRUE]; 
    return TRUE;
}   

the result:

enter image description here

Upvotes: 0

Views: 1105

Answers (1)

Adam Kaplan
Adam Kaplan

Reputation: 1962

Context

The problem is that UINavigationBar provides a very specific and familiar iOS style that Apple wants to keep the same across apps. Default navigation bars don't expand to fit their contents.

When you set set the titleView of navigation item, you are expected to lay out the contents in that view based on the size of the navigation bar, not the other way around.

Solutions

There are several possible solutions:

  1. Change the behavior of that instance of UINavigationBar (not recommended).
  2. Place the UISearchBar underneath the navigation bar as a regular subview.
  3. Use UISearchController

The first option should definitely not be your first solution because it requires you to solve many thorny issues. Use as a last resort.

Option 2 requires the following code changes. Replace self.navigationItem.titleView = self.mySearchBar with:

[self.view addSubview:self.mySearchBar];
UILayoutGuide *guide = self.view.safeAreaLayoutGuide;
[self.mySearchBar.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
[self.mySearchBar.rightAnchor constraintEqualToAnchor:guide.rightAnchor].active = YES;
[self.mySearchBar.leftAnchor constraintEqualToAnchor:guide.leftAnchor].active = YES;

And you are also missing code to resize the UISearchBar after showing the scope bar. The view does not resize itself. So, in your searchBarShouldBeginEditing: method, add this line just before return: [self.mySearchBar sizeToFit];

The third solution may be easier for you depending on your use case. That is, use UISearchController, which includes it's own UISearchBar anchored at the top of the screen. It would look just like solution #2 above as shown in the image below:

enter image description here

Here is a great tutorial on using UISearchController if you are interested.

Upvotes: 1

Related Questions