删除大标题 UINavigationBar 中 UISearchController 顶部的 1px 行

Posted

技术标签:

【中文标题】删除大标题 UINavigationBar 中 UISearchController 顶部的 1px 行【英文标题】:Remove 1px line at top of UISearchController in large titles UINavigationBar 【发布时间】:2018-09-15 16:47:23 【问题描述】:

我正在从具有大样式 UINavigationItem 的视图过渡到具有大样式 UINavigationItemUISearchController 的视图。我已经自定义了UINavigationBar 的背景颜色。

由于某种原因,UINavigationBarUISearchController 之间有 1 像素的线或空格。我可以告诉它来自NavigationBar,因为如果我滚动以使搜索栏贴在顶部,那么该行就会消失。我只是不确定是什么产生了这条线。除了设置barTintColortintColor 之外,我没有使用阴影或任何花哨的东西。如果我不使用大样式标题,我会看到这条线,但仅在视图之间转换时。就像在转换 UISearchController 时,它并没有紧贴 UINavigationBar

感谢任何帮助找出这条线的来源。

更新:在进一步调查中,这似乎仅在 navigationItem.hidesSearchBarWhenScrolling 设置为 false 时发生。如果它最初是隐藏的,那么前一个视图的动画是平滑的,并且显示栏也是平滑的。

【问题讨论】:

我通过添加这一行来修复,[self.navigationBar setTranslucent:false]; @Ben johnson,你找到答案了吗? 【参考方案1】:

测试您描述的导航项和搜索栏设置,我只能在过渡动画期间重现 1px/point 线。

解决方法:该行实际上是UINavigationBar 使用的背景布局视图 (forLastBaselineLayout),由于UISearchBar 的框架有问题,最终可见。设置其背景以匹配您的导航栏颜色以将其隐藏在后站点中

// MARK: UINavigationControllerDelegate

public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) 
    viewController.navigationController?.navigationBar
        .forLastBaselineLayout.backgroundColor = .red // TODO:

确保将实现UINavigationControllerDelegate的对象设置为navigationController.delegate以接收上述委托调用。

另外(不是问题的一部分): UISearchBar 在控制器之间转换(推送和弹出)时似乎表现得很奇怪,尤其是当一个控制器具有/显示 searchBar 而另一个控制器没有时. 解决方法,我发现暂时隐藏搜索栏以防止显示控制器在视觉上更令人愉悦。这是我使用的代码:

public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) 
    if let sender = navigationStack.popLast() 
        prepareSearchBarForTransition(from: sender)
    
    navigationStack = navigationController.children


/// Set only from `navigationController: willShow`
private var navigationStack: [UIViewController] = []

func prepareSearchBarForTransition(from sender: UIViewController) 
    if #available(ios 11.0, *) 
        let searchController = sender.navigationItem.searchController
        sender.navigationItem.searchController = nil
        weak var weakSender = sender
        let navigationTransitionDuration: TimeInterval = 0.33
        DispatchQueue.main.asyncAfter(deadline: .now() + navigationTransitionDuration) 
            /// Reset the search bar.
            weakSender?.navigationItem.searchController = searchController
        
     else 
        // TODO: Check if the above workaround is neccessary for < iOS 11
    

【讨论】:

这里有很多值得思考和玩的地方。非常感谢您仔细研究此事。【参考方案2】:

从整个应用程序中删除一条像素线。

UINavigationBar.appearance().shadowImage = UIImage()

以上代码从整个应用程序中删除了底线。如果只想删除某些特定控制器,则需要管理隐藏/显示底栏图像。对于使用下面的UINavigationBar 扩展来管理隐藏显示底栏一个像素的图像。

extension UIView 

    fileprivate var hairlineImageView: UIImageView? 
        return hairlineImageView(in: self)
    

    fileprivate func hairlineImageView(in view: UIView) -> UIImageView? 
        if let imageView = view as? UIImageView, imageView.bounds.height <= 1.0 
            return imageView
        

        for subview in view.subviews 
            if let imageView = self.hairlineImageView(in: subview) 
                return imageView
            
        
        return nil
    


extension UINavigationBar 

    func hideBottomHairline() 
        self.hairlineImageView?.isHidden = true
    

    func showBottomHairline() 
        self.hairlineImageView?.isHidden = false
    

管理隐藏/显示

self.navigationController?.navigationBar.hideBottomHairline()

self.navigationController?.navigationBar.showBottomHairline()

UIView 以上hairlineImageView 的扩展也可以用于其他UIControls,如UIToolBar

extension UIToolbar 

    func hideBottomHairline() 
        self.hairlineImageView?.isHidden = true
    

    func showBottomHairline() 
        self.hairlineImageView?.isHidden = false
    

【讨论】:

【参考方案3】:

使用以下代码:

navigationController?.navigationBar.shadowImage = UIImage()

【讨论】:

【参考方案4】:

如果你想删除 UINavigationBar 上的 1px 行,在整个应用程序中你可以在 AppDelegate (didFinishLaunchingWithOptions) 中使用下面的代码(测试代码)

UINavigationBar.appearance().shadowImage = UIImage()

【讨论】:

以上是关于删除大标题 UINavigationBar 中 UISearchController 顶部的 1px 行的主要内容,如果未能解决你的问题,请参考以下文章

UINavigationBar 大标题重影

带有大标题的 UINavigationBar 没有背景图片

iOS 11 中 UINavigationBar 大标题的默认字体?

从 uinavigationbar 中删除子视图

如何在 iOS 11 中引入的 UINavigationBar 的大标题视图上添加自定义视图

UINavigationBar 大标题在执行 segues 时不调整大小