iOS:在导航栏中显示搜索栏时隐藏范围栏

Posted

技术标签:

【中文标题】iOS:在导航栏中显示搜索栏时隐藏范围栏【英文标题】:iOS: Scope bar hidden when search bar is displayed in navigation bar 【发布时间】:2014-12-29 22:39:40 【问题描述】:

我正在尝试获取一个搜索栏,它是导航栏中的范围,就像视图首次出现的方式一样。如果您只是将 UISearchBar 拖到界面构建器中的表格视图控制器上,它就会像标题单元格一样放置在您的表格中。然后,当你点击它时,它会动画成我在下面的阵型。问题是我希望它以这种方式开始而无需任何点击,左侧有一个后退按钮,右侧没有取消按钮:

因此,为了在不点击的情况下立即获得搜索栏的焦点,我尝试在 viewDidLoad 中添加 [_searchBar becomeFirstResponder];,但这不起作用。接下来我尝试了:

self.searchDisplayController.displaysSearchBarInNavigationBar = YES;

搜索栏确实会显示在导航栏中,但范围栏不见了,(WHY APPLE WHY)并且有一个尴尬的差距。

我也尝试过继承 UINavigationBar 并使其更高。更改它的大小很容易,但内容在栏的底部对齐,并与您尝试添加的任何内容重叠。

所以要重新迭代,当视图首次出现时,我需要在导航栏中显示搜索栏并带有范围控件,而无需用户点击。我还应该指定这是在 UITableViewController 上(因为页面有一个 UIRefreshConrol),所以简单地将工具栏放在表格视图上方不是一个选项。谢谢。

【问题讨论】:

【参考方案1】:

tl;dr: 不要。

您应该知道,将UISearchBar 添加到UITableViewheaderView 会调用UIKit 中的一些自定义代码,这有助于在启动时隐藏范围栏。虽然在 ios 6 及更早版本中一直显示范围栏更容易,但 iOS 7 改变了这一点。

您的第一种方法,在viewDidLoad 中使用becomeFirstResponder 是一个好主意,但是在视图加载到内存后(例如从NIB 加载)调用此方法。该视图尚未添加到视图层次结构中,因此它不能成为第一响应者。 viewDidAppear: 在视图加载到视图层次结构之后被调用,becomeFirstResponder 实际上允许UISearchBar 接收焦点。

范围栏本身是UISearchBar 的隐藏(默认)子视图。从技术上讲,您可以循环浏览子视图并将其设置为不隐藏:

- (void)viewDidLoad

    [super viewDidLoad];
    [self recurseSubviewsForView:self.searchDisplayController.searchBar];


- (void)recurseSubviewsForView:(UIView *)view

    for (UIView *subview in view.subviews) 
        if ((CGRectGetMinY(subview.frame) == CGRectGetMaxY(self.searchDisplayController.searchBar.frame)) && subview.hidden) 
            subview.hidden = NO;
            self.searchDisplayController.searchBar.showsScopeBar = YES;
            [self.searchDisplayController.searchBar sizeToFit];
        
        [self recurseSubviewsForView:subview];
    

这通常是个坏主意。有一个基本的检查来查看被定位的子视图是包含范围栏的子视图,但这可能会中断,可能不向后兼容,等等。

您必须问自己的真正问题是为什么我希望范围栏始终可见?它现在的工作方式是,当用户点击搜索字段时,范围栏将显示动画,并在搜索字段不再具有焦点时隐藏自身。即使使用上面的“hack”,只要用户点击范围按钮,搜索栏就会获得焦点。当搜索甚至不活动时显示搜索选项有什么意义?如有疑问,请求助于 Apple 的建议。从长远来看,这将使您的生活更轻松,并可能使您的应用外观和行为更好。苹果并不是一时兴起才添加这种交互的。他们疯狂地测试它。这就是为什么很难让它以另一种方式工作。这就是为什么当 UISearchBarUITableViewheaderView 时运行特殊代码的原因......因为它可能对用户更好。

此外,我看到您针对 iOS 8 的屏幕截图,但您的代码截图显示使用 UISearchDisplayController。此范例已被弃用,取而代之的是 UISearchController。请考虑更新。

【讨论】:

很沮丧,我没想过将becomeFirstResponder 放入viewDidAppear:。谢谢!回答您的问题:我希望它始终可见,因为 VC 专门用于搜索。 (查看 Instagram 的搜索选项卡 - 这就是我所追求的)此外,使用 UISearchDisplayController 有一个很好的理由 - 与 iOS7 兼容。它可能在 iOS8 中已被弃用,但它仍然完全有效(并且仍在 IB 的对象库中)。剩下的问题:如果您使用在导航栏中显示搜索栏的选项,为什么Apple会隐藏范围而不考虑设置showsScope = YES 为什么会隐藏范围栏?我不知道,但是it is documented。 “如果您在导航栏中显示的搜索栏中将showsScopeBar 属性设置为YES,系统将引发异常。” 可能是因为导航栏高度不能高到无法显示范围栏。

以上是关于iOS:在导航栏中显示搜索栏时隐藏范围栏的主要内容,如果未能解决你的问题,请参考以下文章

当我点击带有动画的搜索栏时,iOS隐藏导航栏

当我在小于 10 的 ios 版本中隐藏/显示导航栏时,应用程序在进入后台后卡住

ios15在隐藏导航栏时向后半滑动会留下顶部空白空间 - SwiftUI

打开搜索栏时导航栏隐藏

在iOS 7中隐藏导航栏时,如何更改状态栏的颜色?

iOS 7隐藏导航栏时如何更改状态栏的颜色?