且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

当作为子视图添加到UINavigationBar时,UISearchBar不显示“取消”按钮

更新时间:2022-11-11 12:31:50

Figured this out myself!

I tried programmatically creating the UISearchBar and the UISearchDisplayController in a new project, but instead of adding the search bar in the navigation bar, I added it to the main view of a view controller. It worked that way, the Cancel button shows whenever I click on the search bar, except that it doesn't resize back to the original frame when I stop editing--but that's for another discussion. Afterwards, I went back to this project and printed out self.searchBar.showsCancelButton after every line of code where I set it to YES, and it turned out the value is, in fact, YES. So it is the UINavigationBar that, for some reason, does not show the UISearchBar's Cancel button. My solution, then, was to create a fake "Cancel" button in the navigation bar's rightBarButtonItem.

On start, the navigation bar looks like this:

Then, when I click on the search bar, I expand it to a width that's just enough to cover the two left bar button items, but leave some space to keep the right bar button item visible. Then, that right bar button item serves as the Cancel button (I just used a system "Add" button for demo's sake).

When I click on "Search" in the keyboard, or on the plus button, the search bar reverts to its old size and the right bar button item disappears. My full code is below:

HomeViewController.h

#import <UIKit/UIKit.h>
@interface HomeViewController : UIViewController <UISearchBarDelegate>
@end

HomeViewController.m

#import "HomeViewController.h"

@interface HomeViewController ()
@property (strong, nonatomic) UISearchBar *searchBar;
@end

@implementation HomeViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Just some buttons that the search bar will overlap when active.
    UIBarButtonItem *btn1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:nil];
    UIBarButtonItem *btn2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:nil];
    [self.navigationItem setLeftBarButtonItems:@[btn1, btn2] animated:YES];

    self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(100, 0, 150, 44)];    self.searchBar.delegate = self;
    [self.navigationController.navigationBar addSubview:self.searchBar];
}

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
    // Set a fake Cancel button.
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(stopEditing)];

    [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^(){
        self.searchBar.frame = CGRectMake(0, 0, 280, 44);
    } completion:nil];

    // Bring search bar to the front because adding a right bar button
    // item somehow puts it behind the UIBarButtonItems.
    [self.navigationController.navigationBar bringSubviewToFront:self.searchBar];
    return YES;
}

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {

    // Go back to the old frame.
    [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^(){
        self.searchBar.frame = CGRectMake(100, 0, 150, 44);
    } completion:nil];

    // Remove the "Cancel" button.
    self.navigationItem.rightBarButtonItem = nil;

    [self.navigationController.navigationBar bringSubviewToFront:self.searchBar];

    return YES;
}

- (void)stopEditing {
    [self.searchBar resignFirstResponder];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self stopEditing];
}

@end

相关阅读

技术问答最新文章