NavigationBar中的iOS 11 SearchBar


70

在iOS 11中,Apple通过重新设计拐角和变大了高度来重新设计UISearchBar。将UISearchBar添加到navigationBar相当简单,只需使用即可将其设置为navigationItem的titleView navigationItem.titleView = searchBar

但是,在iOS 11中,它似乎不再能正常工作。看看我们使用iOS 10和iOS 11比较相同设置的屏幕

iOS 10 在此处输入图片说明

iOS 11 在此处输入图片说明

您可以清楚地看到SearchBar增大了NavigationBar的大小,但是条形按钮没有正确对齐。而且searchBar不再使用左侧的可用空间。

如此处所述,将searchBar放入包装器视图中以获取iPad上的“取消”按钮,UISearchBar中未显示“取消”按钮,似乎也不起作用了,因为那时根本没有可见的searchBar。

如果有人遇到类似问题或已经知道如何解决/改进此问题,我将非常感激。

这是使用Xcode 9 Beta 4构建的。也许将来的版本会解决此问题。

更新:

由于此问题尚未解决,因此我们决定使用以下解决方案。我们在NavBar中添加了一个新的UIBarButtonItem,然后提供了一个新的ViewController,我们只在其中放置了searchBar,而在NavBar中什么也没用,这似乎可行。使用选择的答案可能是最好的解决方案,因为具有iOS 11的Apple希望我们使用此新设计,即使它不能给我们最初想要的结果。解决此问题的另一种方法可能是自定义SearchBar,但这是另一个主题。


我已经花了几个小时试图解决同样的问题。请在这里检查我的答案:stackoverflow.com/a/53264329/3231194 :)我将其发布为答案,以便可以轻松看到它。谢谢!
Glenn Posadas

Answers:


52

iOS 11中NavigationItem上有一个新的searchController属性。

https://developer.apple.com/documentation/uikit/uinavigationitem/2897305-searchcontroller

像这样使用...

if #available(iOS 11.0, *) {
     navigationItem.searchController = searchController
} else {
     // Fallback on earlier versions
     navigationItem.titleView = searchController?.searchBar
}

在Objective-C中,if语句如下所示:

if (@available(iOS 11.0, *)) {

在iOS 11上,如果未设置navigationItem.hidesSearchBarWhenScrolling = false,则搜索栏最初可能是隐藏的,除非用户向下滚动以显示它。如果确实将其设置为false,则它会堆叠在标题将要去的下方,而无需用户滚动。


1
我的答案与@cook答案相似,但我认为链接和代码可能会有助于澄清。
贾斯汀·多姆尼兹

41
这不会给出原始描述的结果。使用searchController属性会将搜索栏置于导航下方。
Molanda

这适用于iPhone,但不适用于iPad。
Starchand

您是否知道这种情况下的导航栏高度?会改变吗?
精通技术的人

16

您可以通过添加高度44的约束来更改iOS 11中UISearchBar的高度:

if #available(iOS 11.0, *) {
    searchBar.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
}

这样可以缩短顶部和底部边框。我尝试了这种Objective-C解决方案:[[self.notesSearchBar.heightAnchorconstraintEqualToConstant:44.0] setActive:YES],但我不喜欢这种解决方案,因为它会使顶部底部的边距变薄和变得怪异。
coolcool1994 17/09/30

这对我有用。它重新放置我的搜索栏,以保持正确的布局。
克里斯蒂安·阿斯科尼

但是,这是正确的解决方案,尤其是如果您同时针对自己的应用同时定位iOS 10和iOS 11
Rushabh

这解决了高度问题,但没有解决作者所发表的宽度问题。
Delorean

4

我遇到了同样的问题,经过几天的搜索后,我找到了此页面-https://translate.google.com/translate ?hl= zh-CN&sl=zh-CN&u =http://www.jianshu.com/ p / 262f6e34a7d3&prev = search

此页面导致这个混帐回购协议- https://github.com/DreamTravelingLight/searchBarDemo -这个示范项目展示了如何使用旧的方式与titleview的还是有没有大小的问题一个搜索栏。

关键是这些

_searchBar = [self addSearchBarWithFrame:CGRectMake(0, 0, kScreenWidth - 2 * 44 - 2 * 15, 44)];
UIView *wrapView = [[UIView alloc] initWithFrame:_searchBar.frame];
[wrapView addSubview:_searchBar];
self.navigationItem.titleView = wrapView;

如果将UISearchBar嵌入视图中,并将该wrapView设置为titleView,则UISearchBar将具有您为其设置的大小,并将适合预期的导航栏。

谢谢大卫


为什么选择kScreenWidth-2 * 44-2 * 15?
科帕·桑托斯

3

如果您确实想在iOS 11+中使用本机UISearchBar (并避免创建自定义组件的需要),则navigationBar可以为此创建一个容器视图searchBar以完全控制框架。此容器视图将是searchBar您传入的超级视图。

就像是:

class SearchBarContainerView: UIView {

    let searchBar: UISearchBar

    required init?(coder aDecoder: NSCoder) {
        searchBar = UISearchBar()
        super.init(coder: aDecoder)
    }

    init(searchBar: UISearchBar) {
        self.searchBar = searchBar
        super.init(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: 44.0))
        addSubview(searchBar)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        searchBar.frame = bounds
    }
}

接着:

let containerView = SearchBarContainerView(searchBar: searchController.searchBar)
containerView.frame.size.width = navigationController?.navigationBar.frame.size.width ?? 0.0
navigationItem.titleView = containerView

请注意,这只是一个快速演示,还没有准备好navigationBar更改框架(显示旋转等)。您可以使用例如解决autoresizingMask


这可行!另外更新containerView.frameoverride func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { coordinator.animate(alongsideTransition: { // here }... } 就足够了。
ethanhuang13

1

我认为您必须处理将新的UINavigationItem.searchController属性设置为UISearchController对象的问题。这就是您获得Messages中所见的新效果的方式。看来旧的行为已经不复存在了。我希望我是错的,但是整个API都要进行11的大修。我知道它总体上是有问题的,因此,如果此问题得以解决,我们将看到更新的Beta和GM。(在Beta 6编写)


1

这对我有帮助:

    if ([self.navigationItem respondsToSelector:@selector(setSearchController:)])
    {
        [self.navigationItem performSelector:@selector(setSearchController:) withObject:self.searchController];
    }
    else
    {
        self.tableView.tableHeaderView = self.searchController.searchBar;
    }

0

我尝试了一下searchControllersearchBar但发现它searchBar符合我的要求(单击搜索按钮进行搜索)。

-(void)searchBarSetUp{
//Search button to reload the radio content.
self.searchButton.action = @selector(addSearchBarToNavigationTitleView);
self.searchButton.target = self;

//search bar initialization
searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
searchBar.delegate = self;
searchBar.showsCancelButton = YES;
[searchBar sizeToFit]; }

-(void)addSearchBarToNavigationTitleView {
// Install the search bar as the table header.
self.navigationItem.titleView = searchBar;}

如果使用,我也很难处理黑屏searchControl


0

在iOS 14+中进行总结

首先修复推力会导致额外的高度:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationController?.view.setNeedsLayout() // force update layout
    navigationController?.view.layoutIfNeeded() // to fix height of the navigation bar
}

其次将pop固定为原点高度:

extendedLayoutIncludesOpaqueBars = true

以上所有代码均在带有搜索栏的控制器中设置。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.