我正在从具有大样式UINavigationItem
的视图过渡到具有大样式UINavigationItem
和UISearchController
的视图。我已经自定义了UINavigationBar
的背景色。
由于某种原因,UINavigationBar
和UISearchController
之间有1px的线或空格。我可以说它是从NavigationBar
开始的,因为如果滚动以使搜索栏停留在顶部,该行就会消失。我只是不确定是什么产生了这一行。除了设置barTintColor
和tintColor
外,我没有使用阴影或其他任何花哨的东西。如果我不使用大样式的标题,则会看到该行,但仅当在视图之间切换时才看到。就像在过渡UISearchController
时只是不坚持UINavigationBar
一样。
感谢大家帮助我们弄清这条线的来源。
更新:经过进一步调查,似乎只有在navigationItem.hidesSearchBarWhenScrolling
设置为false
时才会发生。如果最初是隐藏的,则前一个视图中的动画是平滑的,并且显示的条也是平滑的。
答案 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()