简体   繁体   English

防止UISearchDisplayController隐藏导航栏

[英]Prevent a UISearchDisplayController from hiding the navigation bar

Whenever a user begins editing a UISearchDisplayController 's search bar, the search controller becomes active and hides the view's navigation bar while presenting the search table view. 每当用户开始编辑UISearchDisplayController的搜索栏时,搜索控制器就会变为活动状态,并在显示搜索表视图时隐藏视图的导航栏。 Is it possible to prevent a UISearchDisplayController from hiding the navigation bar without reimplementing it? 是否可以阻止UISearchDisplayController隐藏导航栏而不重新实现它?

I just debugged a bit into UISearchDisplayController and found that it's calling a private method on UINavigationController to hide the navigation bar. 我刚刚调试了一下UISearchDisplayController并发现它在UINavigationController上调用一个私有方法来隐藏导航栏。 This happens in -setActive:animated:. 这发生在-setActive:animated:。 If you subclass UISearchDisplayController and overwrite this method with the following code you can prevent the navigationBar from being hidden by faking it to be already hidden. 如果您继承UISearchDisplayController并使用以下代码覆盖此方法,则可以通过伪造将其隐藏来阻止navigationBar被隐藏。

- (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];
    }   
}

Let me know if this works for you. 如果这对您有用,请告诉我。 I also hope this won't break in future iOS versions... Tested on iOS 4.0 only. 我也希望在未来的iOS版本中不会破坏...仅在iOS 4.0上测试过。

The simplest solution and no hacks. 最简单的解决方案,没有黑客攻击。

@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

iOS 8中引入的新UISearchController类具有属性hidesNavigationBarDuringPresentation ,如果要保持导航栏可见(默认情况下它仍将被隐藏),您可以将其设置为false。

The above answers didn't work quite right for me. 以上答案对我来说不太适合。 My solution is to fool the UISearchDisplayController into thinking there wasn't a UINavigationController. 我的解决方案是欺骗UISearchDisplayController认为没有UINavigationController。

In your view controller, add this method 在视图控制器中,添加此方法

- (UINavigationController *)navigationController {
    return nil;
}

This had no untoward side effects for me, despite seeming like a really bad idea... If you need to get at the navigation controller, use [super navigationController] . 这对我来说没有任何副作用,尽管看起来像是一个非常糟糕的主意......如果你需要进入导航控制器,请使用[super navigationController]

Since iOS 8.0 the same behavior can be achieved by setting the UISearchController 's self.searchController.hidesNavigationBarDuringPresentation property to false. 从iOS 8.0开始,通过将UISearchControllerself.searchController.hidesNavigationBarDuringPresentation属性设置为false,可以实现相同的行为。

The code in Swift looks like this: Swift中的代码如下所示:

searchController.hidesNavigationBarDuringPresentation = false

Tried this a different way, without subclassing UISearchDisplayController. 尝试这种方式不同,没有子类化UISearchDisplayController。 In your UIViewController class where you set the delegate for UISearchDisplayController, implement searchDisplayControllerDidBeginSearch: and add use 在你为UISearchDisplayController设置委托的UIViewController类中,实现searchDisplayControllerDidBeginSearch:并添加使用

[self.navigationController setNavigationBarHidden:NO animated:YES];

Did the trick for me, hope that helps. 对我来说诀窍,希望有所帮助。

I ran into this while tackling a slightly different problem. 我遇到了一个稍微不同的问题,遇到了这个问题。 While using UISearchDisplayController, I want the search bar to be in the navigation bar (not under). 在使用UISearchDisplayController时,我希望搜索栏位于导航栏中(不在下面)。

It's not hard to put the search bar in the navigation bar (see UISearchBar and UINavigationItem ). 将搜索栏放在导航栏中并不困难(请参阅UISearchBar和UINavigationItem )。 However, UISearchDisplayController assumes the search bar is always underneath the navigation bar and (as discussed here) insists on hiding the navigation bar when entering search, so things look awful. 但是,UISearchDisplayController假定搜索栏始终位于导航栏下方(如此处所述),在进入搜索时坚持隐藏导航栏,因此看起来很糟糕。 Additionally, UISearchDisplayController tints the search bar lighter than normal. 此外,UISearchDisplayController使搜索栏比正常情况更轻。

I found a solution. 我找到了解决方案。 The trick is to (counter-intuitively) unhook UISearchDisplayController from controlling any UISearchBar at all. 诀窍是(反直觉地)解开UISearchDisplayController根本不控制任何UISearchBar。 If using xibs, this means deleting the search bar instance, or at least unhooking the outlet. 如果使用xibs,这意味着删除搜索栏实例,或至少取消插座。 Then create your own UISearchBar: 然后创建自己的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;
}

You will need to manually activate the search display controller when the user taps the search bar (in -searchBarShouldBeginEditing: ) and manually dismiss the search bar when the user ends searching (in -searchDisplayControllerWillEndSearch: ). 当用户点击搜索栏(in- -searchBarShouldBeginEditing:时,您需要手动激活搜索显示控制器,并在用户结束搜索时手动关闭搜索栏(in -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;
}

Really nice solution, but it was crashing my app under iOS6. 非常好的解决方案,但它在iOS6下崩溃我的应用程序。 I had to make the following modification to get it work. 我必须进行以下修改才能使其正常工作。

@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];
        }
    }

This seem to solve it for me. 这似乎解决了我。 Tested in both iOS5/6.1. 在iOS5 / 6.1中都进行了测试。 No visual issues that I could see. 没有我能看到的视觉问题。

- (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 screws things up a bit... for me this worked perfectly: 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];
}

The reason for show/hide the statusbar 显示/隐藏状态栏的原因

I think the best solution is to implement the UISearchDisplayController yourself. 我认为最好的解决方案是自己实现UISearchDisplayController。

It's not that difficult. 这并不困难。 You only need to implement UISearchBarDelegate for your UIViewController and include a UITableView to display your search results. 您只需要为UIViewController实现UISearchBarDelegate并包含一个UITableView来显示您的搜索结果。

@Pavel's works perfectly well. @ Pavel的作品非常好。 However, I was trying to get this into a UIPopoverController and the text in the field gets pushed slightly when the search bar's text field becomes the first responder, and that looks a bit ugly, so I fixed it by calling the super method with animated set to NO . 但是,我试图把它变成一个UIPopoverController,当搜索栏的文本字段成为第一个响应者时,字段中的文本被略微推动,看起来有点难看,所以我通过调用带有animated集的super方法来修复它NO

As jrc pointed out "unhook UISearchDisplayController from controlling any UISearchBar" seems to work for me. 正如jrc所指出的那样“解开UISearchDisplayController来控制任何UISearchBar”似乎对我有用。 If I pass nil as a parameter when creating UISearchDisplayController the navigation bar stays visible at all times: 如果我在创建UISearchDisplayController时将nil作为参数传递,则导航栏始终保持可见:

searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:nil contentsController:self];

I was adding custom navigation bar on my ViewController which was getting hidden on search, a quick but not so good fix was 我在我的ViewController上添加了自定义导航栏,这个导航栏在搜索时被隐藏了,这是一个快速但不太好的修复方法

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
    [self.view addSubview:_navBar];
}

_navBar is UINavigationBar added programmatically, doing this helped me navigation bar from hiding. _navBar是以编程方式添加的UINavigationBar,这样做有助于我隐藏导航栏。

Just wanted to add to stigi answer. 只是想加入stigi的答案。 When you cancel search and start search again - search results table won't be react to touches so you need to add next line 当您取消搜索并再次开始搜索时 - 搜索结果表将不会对触摸作出反应,因此您需要添加下一行

self.searchResultsTableView.alpha = 1;

So updated code looks next way 所以更新的代码看起来是下一个

 - (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];
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM