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

时间:2013-09-28 19:41:00

标签: iphone ios objective-c cocoa-touch uisearchbar

我正在关注https://stackoverflow.com/a/14235624/855680的答案,为我的UISearchBar设置动画,以较小的宽度开始,然后在激活时扩展到iPhone屏幕的整个宽度。它按预期展开,但“取消”按钮根本不显示。我尝试在setShowsCancelButton:animatedsearchBarTextDidBeginEditing:中调用searchDisplayControllerWillBeginSearch:,但无济于事。我错过了什么?这是我的代码:

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

4 个答案:

答案 0 :(得分:2)

自己想出来了!

我尝试在新项目中以编程方式创建UISearchBarUISearchDisplayController,但我没有在导航栏中添加搜索栏,而是将其添加到视图控制器的主视图中。它以这种方式工作,每当我点击搜索栏时,“取消”按钮就会显示,但是当我停止编辑时它不会调整回原始帧 - 但这是另一个讨论。之后,我回到了这个项目并在我将其设置为self.searchBar.showsCancelButton的每行代码后打印出YES,事实证明该值是YES。因此,UINavigationBar由于某种原因未显示UISearchBar的取消按钮。我的解决方案是在导航栏rightBarButtonItem中创建一个虚假的“取消”按钮。

开始时,导航栏如下所示:

enter image description here

然后,当我点击搜索栏时,我将其展开到足以覆盖两个左栏按钮项的宽度,但留出一些空格以保持右栏按钮项可见。然后,右边的条形按钮项目用作取消按钮(为了演示,我只使用了系统“添加”按钮)。

enter image description here

当我点击键盘上的“搜索”或加号按钮时,搜索栏将恢复为旧尺寸,右侧栏按钮项目将消失。我的完整代码如下:

<强> 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

答案 1 :(得分:1)

您应该设置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];

}

答案 2 :(得分:0)

是否有任何理由将搜索栏放在导航栏中?我认为如果您将搜索栏放在视图中的某个位置,您的代码应该可以正常工作,如果您想在其中添加内容,导航栏很棘手您通常会定义视图或项目以替换导航栏中的对象,如rightbarbuttonitem / leftbarbuttonitem或标题

    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:infoButton];

答案 3 :(得分:0)

这是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];
}

现在您将有一个带取消按钮的搜索栏。