防止UISearchDisplayController隐藏导航栏

时间:2010-05-11 17:51:22

标签: iphone iphone-sdk-3.0 uinavigationcontroller uisearchdisplaycontroller

每当用户开始编辑UISearchDisplayController的搜索栏时,搜索控制器将变为活动状态,并在显示搜索表视图时隐藏视图的导航栏。是否可以阻止UISearchDisplayController隐藏导航栏而不重新实现它?

15 个答案:

答案 0 :(得分:60)

我刚刚调试了一下UISearchDisplayController并发现它正在调用UINavigationController上的私有方法来隐藏导航栏。这发生在-setActive:animated:。如果您继承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];
    }   
}

如果这对您有用,请告诉我。我也希望在未来的iOS版本中不会破坏...仅在iOS 4.0上测试。

答案 1 :(得分:52)

最简单的解决方案,没有黑客攻击。

@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

答案 2 :(得分:46)

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

答案 3 :(得分:28)

上述答案对我来说并不合适。我的解决方案是欺骗UISearchDisplayController认为没有UINavigationController。

在视图控制器中,添加此方法

- (UINavigationController *)navigationController {
    return nil;
}

这对我来说没有任何副作用,尽管看起来真的很糟糕......如果你需要进入导航控制器,请使用[super navigationController]

答案 4 :(得分:10)

从iOS 8.0开始,通过将UISearchController的{​​{1}}属性设置为false,可以实现相同的行为。

Swift中的代码如下所示:

self.searchController.hidesNavigationBarDuringPresentation

答案 5 :(得分:9)

尝试不同的方式,没有子类化UISearchDisplayController。在你为UISearchDisplayController设置委托的UIViewController类中,实现searchDisplayControllerDidBeginSearch:并添加使用

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

对我而言,希望有所帮助。

答案 6 :(得分:4)

我遇到了一个稍微不同的问题。使用UISearchDisplayController时,我希望搜索栏在的导航栏中(不在下面)

将搜索栏放在导航栏中并不困难(请参阅UISearchBar and 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;
}

答案 7 :(得分:3)

非常好的解决方案,但它在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];
        }
    }

答案 8 :(得分:3)

这似乎为我解决了这个问题。在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];
}

答案 9 :(得分:3)

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

显示/隐藏状态栏的原因

答案 10 :(得分:1)

我认为最好的解决方案是自己实现UISearchDisplayController。

这并不困难。您只需要为UIViewController实现UISearchBarDelegate并包含一个UITableView来显示您的搜索结果。

答案 11 :(得分:0)

@ Pavel的作品完美无缺。但是,我试图把它变成一个UIPopoverController,当搜索栏的文本字段成为第一个响应者时,字段中的文本被轻微推动,看起来有点难看,所以我通过调用super来修复它方法用 animated设置为NO

答案 12 :(得分:0)

正如jrc所指出的那样“解开UISearchDisplayController来控制任何UISearchBar”似乎对我有用。如果我在创建UISearchDisplayController时将nil作为参数传递,则导航栏始终保持可见:

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

答案 13 :(得分:0)

我在我的ViewController上添加了自定义导航栏,这个导航栏在搜索时被隐藏了,这是一个快速但不太好的修复

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

_navBar是以编程方式添加的UINavigationBar, 这样做有助于导航栏隐藏。

答案 14 :(得分:0)

只是想加入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];
    }
}