每当用户开始编辑UISearchDisplayController
的搜索栏时,搜索控制器就会激活并隐藏视图的导航栏,同时呈现搜索表视图。是否可以防止UISearchDisplayController
隐藏导航栏而不重新实现它?
15 回答
我只是对 UISearchDisplayController 进行了一些调试,发现它正在调用 UINavigationController 上的私有方法来隐藏导航栏。这发生在 -setActive:animated: 中。如果你继承 UISearchDisplayController 并用下面的代码覆盖这个方法,你可以通过假装它已经隐藏来防止导航栏被隐藏。
- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
if(self.active == visible) return;
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
if (visible) {
[self.searchBar becomeFirstResponder];
} else {
[self.searchBar resignFirstResponder];
}
}
让我知道这是否适合您。我也希望这不会在未来的 iOS 版本中中断......仅在 iOS 4.0 上测试。
最简单的解决方案,没有黑客。
@interface MySearchDisplayController : UISearchDisplayController
@end
@implementation MySearchDisplayController
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
[super setActive: visible animated: animated];
[self.searchContentsController.navigationController setNavigationBarHidden: NO animated: NO];
}
@end
UISearchController
iOS 8 引入的新类有一个属性hidesNavigationBarDuringPresentation
,如果你想保持导航栏可见,你可以设置为 false(默认情况下它仍然是隐藏的)。
上面的答案对我来说不太合适。我的解决方案是欺骗 UISearchDisplayController 认为没有 UINavigationController。
在您的视图控制器中,添加此方法
- (UINavigationController *)navigationController {
return nil;
}
尽管这似乎是一个非常糟糕的主意,但这对我来说没有任何不良副作用……如果您需要使用导航控制器,请使用[super navigationController]
.
从 iOS 8.0 开始,可以通过将UISearchController
'self.searchController.hidesNavigationBarDuringPresentation
属性设置为 false 来实现相同的行为。
Swift 中的代码如下所示:
searchController.hidesNavigationBarDuringPresentation = false
尝试了一种不同的方式,没有继承 UISearchDisplayController。在为 UISearchDisplayController 设置委托的 UIViewController 类中,实现 searchDisplayControllerDidBeginSearch: 并添加使用
[self.navigationController setNavigationBarHidden:NO animated:YES];
为我做了诀窍,希望有帮助。
我在处理一个稍微不同的问题时遇到了这个问题。在使用 UISearchDisplayController 时,我希望搜索栏位于导航栏中(而不是下方)。
将搜索栏放在导航栏中并不难(参见UISearchBar 和 UINavigationItem)。但是,UISearchDisplayController 假定搜索栏始终位于导航栏下方,并且(如这里所讨论的)坚持在输入搜索时隐藏导航栏,因此看起来很糟糕。此外,UISearchDisplayController 使搜索栏的颜色比正常颜色浅。
我找到了解决方案。诀窍是(反直觉地)将 UISearchDisplayController 完全从控制任何 UISearchBar 中解脱出来。如果使用 xibs,这意味着删除搜索栏实例,或者至少解开插座。然后创建自己的 UISearchBar:
- (void)viewDidLoad
{
[super viewDidLoad];
UISearchBar *searchBar = [[[UISearchBar alloc] init] autorelease];
[searchBar sizeToFit]; // standard size
searchBar.delegate = self;
// Add search bar to navigation bar
self.navigationItem.titleView = searchBar;
}
您需要在用户点击搜索栏时手动激活搜索显示控制器(在 中-searchBarShouldBeginEditing:
),并在用户结束搜索时手动关闭搜索栏(在 中-searchDisplayControllerWillEndSearch:
)。
#pragma mark <UISearchBarDelegate>
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
// Manually activate search mode
// Use animated=NO so we'll be able to immediately un-hide it again
[self.searchDisplayController setActive:YES animated:NO];
// Hand over control to UISearchDisplayController during the search
searchBar.delegate = (id <UISearchBarDelegate>)self.searchDisplayController;
return YES;
}
#pragma mark <UISearchDisplayDelegate>
- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController
*)controller {
// Un-hide the navigation bar that UISearchDisplayController hid
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController
*)controller {
UISearchBar *searchBar = (UISearchBar *)self.navigationItem.titleView;
// Manually resign search mode
[searchBar resignFirstResponder];
// Take back control of the search bar
searchBar.delegate = self;
}
非常好的解决方案,但它在 iOS6 下使我的应用程序崩溃。我必须进行以下修改才能使其正常工作。
@implementation ICSearchDisplayController
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
if (visible == YES) {
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
} else {
[super setActive:NO animated:NO];
}
}
这似乎为我解决了这个问题。在 iOS5/6.1 中测试。没有我能看到的视觉问题。
- (void)viewDidAppear
{
[super viewDidAppear];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardWillAppear:(NSNotification *)notification
{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
-(void)viewDidLayoutSubviews{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
iOS 7 有点搞砸了……对我来说,这非常有效:
/**
* Overwrite the `setActive:animated:` method to make sure the UINavigationBar
* does not get hidden and the SearchBar does not add space for the statusbar height.
*
* @param visible `YES` to display the search interface if it is not already displayed; NO to hide the search interface if it is currently displayed.
* @param animated `YES` to use animation for a change in visible state, otherwise NO.
*/
- (void)setActive:(BOOL)visible animated:(BOOL)animated
{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}
显示/隐藏状态栏的原因
我认为最好的解决方案是自己实现 UISearchDisplayController。
这并不难。您只需要为您的 UIViewController 实现 UISearchBarDelegate 并包含一个 UITableView 来显示您的搜索结果。
我在我的 ViewController 上添加了自定义导航栏,该导航栏在搜索时被隐藏了,一个快速但不太好的修复是
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[self.view addSubview:_navBar];
}
_navBar 是 UINavigationBar 以编程方式添加的,这样做有助于我隐藏导航栏。
正如 jrc 指出的那样,“从控制任何 UISearchBar 中解开 UISearchDisplayController”似乎对我有用。如果我在创建 UISearchDisplayController 时将 nil 作为参数传递,则导航栏始终保持可见:
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];
@Pavel 的作品非常好。但是,我试图将其放入 UIPopoverController 中,当搜索栏的文本字段成为第一响应者时,字段中的文本会被轻微推送,这看起来有点难看,所以我通过调用set to的super
方法
来修复它。animated
NO
只是想添加到 stigi 答案。当您取消搜索并重新开始搜索时 - 搜索结果表不会对触摸做出反应,因此您需要添加下一行
self.searchResultsTableView.alpha = 1;
所以更新的代码看起来是下一个方式
- (void)setActive:(BOOL)visible animated:(BOOL)animated;
{
if(self.active == visible) return;
if (visible) {
[self.searchContentsController.navigationController setNavigationBarHidden:YES animated:NO];
[super setActive:visible animated:animated];
[self.searchContentsController.navigationController setNavigationBarHidden:NO animated:NO];
self.searchResultsTableView.alpha = 1;
[self.searchBar becomeFirstResponder];
} else {
[super setActive:visible animated:animated];
[self.searchBar resignFirstResponder];
}
}