删除大标题 UINavigationBar 中 UISearchController 顶部的 1px 行
Remove 1px line at top of UISearchController in large titles UINavigationBar
我正在从具有大样式 UINavigationItem
的视图转换为具有大样式 UINavigationItem
和 UISearchController
的视图。我自定义了 UINavigationBar
.
的背景颜色
由于某种原因,UINavigationBar
和 UISearchController
之间有一条 1px 的线或 space。我可以从 NavigationBar
中看出它,因为如果我滚动以使搜索栏停留在顶部,该行就会消失。我只是不确定是什么产生了这条线。除了设置 barTintColor
和 tintColor
之外,我没有使用阴影或任何花哨的东西。如果我不使用大样式标题,我会看到这条线,但只有在视图之间转换时才会看到。这就像在转换 UISearchController
时并没有正确地粘附到 UINavigationBar
.
如果您能帮助我们找出这条线的来源,我们将不胜感激。
更新:经过进一步调查,似乎只有当 navigationItem.hidesSearchBarWhenScrolling
设置为 false
时才会发生这种情况。如果一开始是隐藏的,那么上一个视图的动画是平滑的,显示条形图也是平滑的。
使用以下代码:
navigationController?.navigationBar.shadowImage = UIImage()
如果你想删除 UINavigationBar 上的 1px 行,在整个应用程序中,你可以在 AppDelegate (didFinishLaunchingWithOptions) 中使用以下代码(测试代码)
UINavigationBar.appearance().shadowImage = UIImage()
从整个应用程序中删除一条像素线。
UINavigationBar.appearance().shadowImage = UIImage()
以上代码从整个应用程序中删除底线。如果只想删除某些特定控制器,则需要管理 hide/show 底部栏图像。对于下面使用 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
}
}
To manage hide/show
self.navigationController?.navigationBar.hideBottomHairline()
self.navigationController?.navigationBar.showBottomHairline()
Above UIView
extension for hairlineImageView
can also be used for other UIControls
like UIToolBar
extension UIToolbar {
func hideBottomHairline() {
self.hairlineImageView?.isHidden = true
}
func showBottomHairline() {
self.hairlineImageView?.isHidden = false
}
}
测试您描述的导航项和搜索栏设置,我只能在过渡动画期间重现 1px/point 线。
解决方法:这一行实际上是背景布局视图(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
在控制器之间转换(推送和弹出)时似乎表现得很奇怪,尤其是当一个 has/show a 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
}
}
我正在从具有大样式 UINavigationItem
的视图转换为具有大样式 UINavigationItem
和 UISearchController
的视图。我自定义了 UINavigationBar
.
由于某种原因,UINavigationBar
和 UISearchController
之间有一条 1px 的线或 space。我可以从 NavigationBar
中看出它,因为如果我滚动以使搜索栏停留在顶部,该行就会消失。我只是不确定是什么产生了这条线。除了设置 barTintColor
和 tintColor
之外,我没有使用阴影或任何花哨的东西。如果我不使用大样式标题,我会看到这条线,但只有在视图之间转换时才会看到。这就像在转换 UISearchController
时并没有正确地粘附到 UINavigationBar
.
如果您能帮助我们找出这条线的来源,我们将不胜感激。
更新:经过进一步调查,似乎只有当 navigationItem.hidesSearchBarWhenScrolling
设置为 false
时才会发生这种情况。如果一开始是隐藏的,那么上一个视图的动画是平滑的,显示条形图也是平滑的。
使用以下代码:
navigationController?.navigationBar.shadowImage = UIImage()
如果你想删除 UINavigationBar 上的 1px 行,在整个应用程序中,你可以在 AppDelegate (didFinishLaunchingWithOptions) 中使用以下代码(测试代码)
UINavigationBar.appearance().shadowImage = UIImage()
从整个应用程序中删除一条像素线。
UINavigationBar.appearance().shadowImage = UIImage()
以上代码从整个应用程序中删除底线。如果只想删除某些特定控制器,则需要管理 hide/show 底部栏图像。对于下面使用 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
}
}
To manage hide/show
self.navigationController?.navigationBar.hideBottomHairline()
self.navigationController?.navigationBar.showBottomHairline()
Above
UIView
extension forhairlineImageView
can also be used for otherUIControls
likeUIToolBar
extension UIToolbar {
func hideBottomHairline() {
self.hairlineImageView?.isHidden = true
}
func showBottomHairline() {
self.hairlineImageView?.isHidden = false
}
}
测试您描述的导航项和搜索栏设置,我只能在过渡动画期间重现 1px/point 线。
解决方法:这一行实际上是背景布局视图(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
在控制器之间转换(推送和弹出)时似乎表现得很奇怪,尤其是当一个 has/show a 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
}
}