Reputation: 13511
I'm following the answer at https://stackoverflow.com/a/14235624/855680 to animate my UISearchBar
which starts off with a smaller width, then expands to the full width of the iPhone screen when active. It expands as expected, except that the Cancel button does not appear at all. I've tried calling setShowsCancelButton:animated
in both searchBarTextDidBeginEditing:
and searchDisplayControllerWillBeginSearch:
, but to no avail. What am I missing? Here's my code:
HomeViewController.h
#import <UIKit/UIKit.h>
@interface HomeViewController : UIViewController <UISearchBarDelegate, UISearchDisplayDelegate>
@end
HomeViewController.m
#import "HomeViewController.h"
@interface HomeViewController ()
@property (strong, nonatomic) UISearchDisplayController *sdc;
@property (strong, nonatomic) UISearchBar *searchBar;
@end
@implementation HomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Add dummy buttons to navigation bar.
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];
// Add UISearchBar.
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(100, 0, 150, 44)];
self.sdc = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.sdc.delegate = self;
[self.navigationController.navigationBar addSubview:self.searchBar];
}
// From this point onwards, pretty much copy-paste from the StackOverflow answer.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(adjustFrame:) name:UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:@selector(adjustFrame:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[nc removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
- (void)adjustFrame:(NSNotification *) notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationBeginsFromCurrentState:YES];
if ([[notification name] isEqual:UIKeyboardWillHideNotification]) {
// revert back to the normal state.
self.searchBar.frame = CGRectMake (100, 0, 150, 44);
}
else {
//resize search bar
self.searchBar.frame = CGRectMake (0,0,320,self.searchBar.frame.size.height);
}
[UIView commitAnimations];
}
// Try to catch the editing event and display the Cancel button.
// BOTH DON'T WORK.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
[controller.searchBar setShowsCancelButton:YES animated:YES];
}
@end
Upvotes: 2
Views: 5105
Reputation: 2340
Here is the simplest solution for iOS7.
- (void) viewDidLoad
{
self.navigationItem.leftBarButtonItem = LEFT_ITEM;
self.navigationItem.rightBarButtonItem = SEARCH_ICON;
}
- (void)searchIconPressed
{
self.navigationItem.leftBarButtonItem = nil;
self.navigationItem.rightBarButtonItem = nil;
self.navigationItem.titleView = self.searchBar;
UIBarButtonItem* cancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelSearch)];
[self.navigationItem setRightBarButtonItem:cancel animated:YES];
[self.searchBar becomeFirstResponder];
}
Now you will have a search bar with Cancel button also.
Upvotes: 0
Reputation: 1245
Is there any reason why you are putting the search bar in the navigation bar? I think your code should work if your were placing the search bar somewhere in the view, the navigation bar is tricky if you wish to put something in it you generally define views or items to replace the objects in your navbar like the rightbarbuttonitem / leftbarbuttonitem or title
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:infoButton];
Upvotes: 0
Reputation: 13511
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
Upvotes: 2
Reputation: 560
You should set delegate of UISearchBar self.searchBar.delegate = self;
- (void)viewDidLoad {
[super viewDidLoad];
// Add dummy buttons to navigation bar.
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];
// Add UISearchBar.
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(100, 0, 150, 44)];
self.sdc = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.sdc.delegate = self;
self.searchBar.delegate = self;
[self.navigationController.navigationBar addSubview:self.searchBar];
}
Upvotes: 1