iOS 11 SearchBar in NavigationBar

一世执手 提交于 2019-11-28 15:27:30
Justin Domnitz

There's a new searchController property on navigationItem in iOS 11.

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

Use like this...

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

In Objective-C the if statement looks like this:

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

On iOS 11, if you don't set navigationItem.hidesSearchBarWhenScrolling = false, the search bar may initially be hidden, unless the user scrolls down to reveal it. If you do set it to false, it appears stacked below where the title would go without the user having to scroll.

zgjie

You can change the height of UISearchBar in iOS 11 by adding a constraint of height 44:

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

I was having the same issue and after a few day googling the issue, I found this page - https://translate.google.com/translate?hl=en&sl=zh-CN&u=http://www.jianshu.com/p/262f6e34a7d3&prev=search.

This page leads to this git repo - https://github.com/DreamTravelingLight/searchBarDemo - this demo project shows how to use the old way with titleView to still have a searchBar without the sizing issue.

The key lines are these

_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;

If you embed the UISearchBar inside a view, and set that wrapView as the titleView, the UISearchBar will have the size you set for it, and will fit the nav bar as intended.

Thanks, David

I think you'll have to deal with setting the new UINavigationItem.searchController property to your UISearchController object. That's how you get the new effect as seen in Messages. It looks like the old behavior is just plain gone. I hope I'm wrong, but the whole API got an overhaul for 11. I know it's buggy in general so we'll see with newer betas and the GM if this gets fixed. (Writing at time of Beta 6)

This helped me:

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

If you really want to use the native UISearchBar (and avoid the needs of creating your custom components) in the iOS 11+ navigationBar, you could create a container view for that searchBar to have full control over the frame. This container view would be the superview of the searchBar you pass in.

Something like:

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

And then:

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

Note that this is just a quick demo and is not ready for navigationBar frame changes (display rotation etc.). You could solve that with e.g. autoresizingMask.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!