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

时间:2018-09-15 16:47:23

标签: ios uinavigationbar uisearchcontroller preferslargetitles

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

由于某种原因,UINavigationBarUISearchController之间有1px的线或空格。我可以说它是从NavigationBar开始的,因为如果滚动以使搜索栏停留在顶部,该行就会消失。我只是不确定是什么产生了这一行。除了设置barTintColortintColor外,我没有使用阴影或其他任何花哨的东西。如果我不使用大样式的标题,则会看到该行,但仅当在视图之间切换时才看到。就像在过渡UISearchController时只是不坚持UINavigationBar一样。

感谢大家帮助我们弄清这条线的来源。

更新:经过进一步调查,似乎只有在navigationItem.hidesSearchBarWhenScrolling设置为false时才会发生。如果最初是隐藏的,则前一个视图中的动画是平滑的,并且显示的条也是平滑的。

Example screenshot of line

4 个答案:

答案 0 :(得分:3)

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

解决方法:此行实际上是forLastBaselineLayout使用的背景布局视图UINavigationBar),由于存在错误的框架,最终可见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
    }
}

答案 1 :(得分:1)

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

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的{​​{1}}扩展名也可以用于其他hairlineImageView,例如UIControls

UIToolBar

答案 2 :(得分:0)

使用以下代码:

navigationController?.navigationBar.shadowImage = UIImage()

答案 3 :(得分:0)

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

UINavigationBar.appearance().shadowImage = UIImage()