如何快速删除导航栏的边框?
Posted
技术标签:
【中文标题】如何快速删除导航栏的边框?【英文标题】:How to remove border of the navigationBar in swift? 【发布时间】:2014-12-10 23:22:55 【问题描述】:我一直在尝试删除 navigationBars 边框,但没有运气。我已经研究过,人们似乎告诉将 shadowImage 和 BackgroundImage 设置为零,但这在我的情况下不起作用。
我的代码
self.navigationController?.navigationBar.barTintColor = UIColor(rgba: "#4a5866")
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: ""), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage(named: "")
插图:
【问题讨论】:
【参考方案1】:问题在于这两行:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: ""), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage(named: "")
由于您没有没有名称的图像,UIImage(named: "")
返回nil
,这意味着默认行为开始:
当非零时,显示自定义阴影图像而不是默认阴影图像。要显示自定义阴影,还必须使用 -setBackgroundImage:forBarMetrics: 设置自定义背景图像(如果使用默认背景图像,将使用默认阴影图像)。
您需要一个真正的空图像,所以只需使用UIImage()
进行初始化:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
【讨论】:
这个答案确实有效。因为如果使用接受的答案(代码),它的删除工具栏 imageViews 到。 这应该是公认的答案。从 UINavigationBar.appearance() 设置时也有效 这应该是 Swift 3 接受的答案。接受的答案在 Swift 2 中对我有效,但在 Swift 3 中无效 对于 swift3,您应该编写稍微不同的方式: self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default) self.navigationController?.navigationBar.shadowImage = UIImage() 此方法与ios 11中的大标题冲突【参考方案2】:斯威夫特 4 和斯威夫特 5
移除边框:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.layoutIfNeeded()
恢复边框:
self.navigationController?.navigationBar.setBackgroundImage(nil, for:.default)
self.navigationController?.navigationBar.shadowImage = nil
self.navigationController?.navigationBar.layoutIfNeeded()
【讨论】:
这里需要 layoutIfNeeded() 吗? 是的 korgx9,我们需要它。否则它不会改变颜色,直到下一次绘制。【参考方案3】:使用 Swift 2,您可以这样做:
AppDelegate 文件
内部 func 应用程序(..., didFinishLaunchingWithOptions launchOptions:...)
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarMetrics: .Default)
对于 Swift 3:
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
【讨论】:
这是全面的答案! 最好在 Appdelegate 中编写这些有用的默认值,而不是在奇怪的地方编写它们。正确答案:)【参考方案4】:在 UINavigationBar 的扩展中写这个就行了
extension UINavigationBar
func shouldRemoveShadow(_ value: Bool) -> Void
if value
self.setValue(true, forKey: "hidesShadow")
else
self.setValue(false, forKey: "hidesShadow")
在你的 viewController 中...
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
self.navigationController?.navigationBar.shouldRemoveShadow(true)
要为任何 viewController 撤消此操作,只需传递 false。
【讨论】:
这很好用,但是如果对于导航堆栈上的所有 vcs,它会隐藏。如果您在 vc1 中使用它,并且 vc1 可以推送到 vc2,那么它也将隐藏在 vc2 上。要在 vc2 中显示阴影,您必须在 viewDidLoad 中将其设置为 false。问题是当您弹回 vc1 时,它会再次显示,因为它在 vc2 中已重置。您必须使用逻辑来回走动,这可能不值得。但是,如果您根本不希望阴影图像显示在任何 vcs 上,那么这是最简单的方法 假设我们有一堆带有 5 个 viewControllers 的 viewControllers(我们已经在第一个 viewControllers 中隐藏了阴影)。现在仅针对第 3 个 viewController,我不想隐藏阴影。所以,我将在 viewWillAppear 中使用 FALSE 调用该方法,在第 3 个 viewController 的 viewWillDisappear 中使用 TRUE 调用该方法。仅此而已! 你的想法绝对正确,好!不要以为我敲了你的答案,因为它非常简洁有效,我也投了赞成票。我用它来删除它和导航栏的错误消息。我发现的问题是在 vc1 中将其删除但显示为 vc2 但如果 vc2 中出现错误则在 viewWillDisappear 中删除它可能不起作用。但这又是一个非常独特的情况。我确实喜欢 viewWillDisappear 用于一般案例的想法,您应该将其添加到您的答案中。无论您的代码是否有效,这都是消除阴影的简单方法! ???? 像魅力一样工作。只是想确保这不是私人设置? 这是一个很好的答案!我添加了一个简化代码的答案。【参考方案5】:这将完全删除阴影图像
for parent in self.navigationController!.navigationBar.subviews
for childView in parent.subviews
if(childView is UIImageView)
childView.removeFromSuperview()
【讨论】:
对我来说也适用这个解决方案,而@Nate Cook 的回答没有用。 :S 天哪!!经过所有的搜索,这是唯一有效的方法。 它有效,但我在导航栏中也有一个菜单图标,但它消失了:/我只想删除边框。帮助:/ 这对我有用,但是在推送新的 ViewController 之后,它会从那里删除该行。我怎样才能防止它呢? 这在 iOS 11 上对我不起作用。 removeFromSuperview 已成功调用,但该死的行仍然存在。看起来它正在重新添加到导航栏。【参考方案6】:斯威夫特 5
当使用 setBackgroundImage / shadowImage 隐藏细线时,会有一点延迟。这种方法消除了延迟。归功于Chameleon Framework。这是他们使用的方法(在 ObjC 中)
extension UINavigationController
func hideHairline()
if let hairline = findHairlineImageViewUnder(navigationBar)
hairline.isHidden = true
func restoreHairline()
if let hairline = findHairlineImageViewUnder(navigationBar)
hairline.isHidden = false
func findHairlineImageViewUnder(_ view: UIView) -> UIImageView?
if view is UIImageView && view.bounds.size.height <= 1.0
return view as? UIImageView
for subview in view.subviews
if let imageView = self.findHairlineImageViewUnder(subview)
return imageView
return nil
【讨论】:
FWIW,这是唯一适用于 iOS 13.4 的解决方案...【参考方案7】:let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithTransparentBackground()
【讨论】:
大声笑,这是一个内置功能。谷歌搜索了几页代码来找到这一行。 仅限 iOS 13 你真的拯救了我的一天。 self.navigationController?.navigationBar.shadowImage = UIImage() 自 iOS 15 起不再工作。谢谢?【参考方案8】:在设置色调之前将barStyle
设置为.Black
:
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barStyle = .Black
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()
【讨论】:
这真的有效吗?还是我想多了? @joe 很好,它在这里工作:-) 它不适合你吗? 就是这样,它确实有效。我只是想知道是否有解释为什么将 barStyle 变为黑色然后将整个 barTintColor 变为蓝色:) 可能将其设置为黑色和不透明,它会关闭导航栏中的某些图层/视图... 我试过用这个,它确实删除了底线,但是如果使用白色的条形,标题是不可见的:/【参考方案9】:Luca Davanzo 的回答很棒,但它在 iOS 10 中不起作用。我将其更改为在 iOS 10 及更低版本中起作用。
for parent in navigationController!.view.subviews
for child in parent.subviews
for view in child.subviews
if view is UIImageView && view.frame.height == 0.5
view.alpha = 0
您还可以扩展 UINavigationController 并从中调用它。 removeFromSuperview()
上线将无法在 iOS 10 上运行,所以我只是将 alpha 设置为 0,以便此调用在任何地方都兼容。
【讨论】:
不错,有什么方法可以在导航时显示/隐藏某些视图控制器中的阴影? 您应该检查具有height >= 1.0
的高度。在具有 3 倍视网膜屏幕(例如 8 Plus、XR...)的 iPhone 机型上,发际线的高度为 0.33。【参考方案10】:
要在 Swift 3+ 中从 UINavigationBar 中删除边框,请使用:
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
UINavigationBar.appearance().isTranslucent = false
【讨论】:
【参考方案11】:只有这对我有用,
self.navigationController?.navigationBar.shadowImage = UIImage()
Ref
【讨论】:
【参考方案12】:Jack Chen 更快捷的方法:
extension UINavigationController
var isHiddenHairline: Bool
get
guard let hairline = findHairlineImageViewUnder(navigationBar) else return true
return hairline.isHidden
set
if let hairline = findHairlineImageViewUnder(navigationBar)
hairline.isHidden = newValue
private func findHairlineImageViewUnder(_ view: UIView) -> UIImageView?
if view is UIImageView && view.bounds.size.height <= 1.0
return view as? UIImageView
for subview in view.subviews
if let imageView = self.findHairlineImageViewUnder(subview)
return imageView
return nil
使用:
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
navigationController?.isHiddenHairline = true
override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(animated)
navigationController?.isHiddenHairline = false
【讨论】:
这一定是最佳答案!【参考方案13】:对于 Swift 3
在viewDidLoad
方法中
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
【讨论】:
【参考方案14】:为 Swift 4 更新,以防有人想知道
navigationBar.shadowImage = UIImage()
navigationBar.backIndicatorImage = UIImage()
现在更简洁了。
【讨论】:
【参考方案15】:如果你想在不改变背景颜色的情况下这样做:
// Remove the border ImageView from the NavigationBar background
func hideBottomBorder()
for view in navigationBar.subviews.filter( NSStringFromClass($0.dynamicType) == "_UINavigationBarBackground" ) as [UIView]
if let imageView = view.subviews.filter( $0 is UIImageView ).first as? UIImageView
imageView.removeFromSuperview()
注意: 这可能会在生产应用程序上崩溃。显然 NavigationBar 不喜欢它的视图消失
【讨论】:
【参考方案16】:接受的答案对我有用,但我注意到当我希望阴影图像在弹出或向前推到另一个 vc 时重新出现时,导航栏中会出现明显的闪烁。
使用这个方法navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
在 viewWillAppear 中,阴影条隐藏在当前可见的视图控制器中。
使用这两种方法
navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
navigationController?.navigationBar.setValue(false, forKey: "hidesShadow")
在 viewWillDisappear 中,闪烁仍然会发生,但只有当阴影图像重新出现而不是导航栏本身时才会发生。
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
// 1. hide the shadow image in the current view controller you want it hidden in
navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
navigationController?.navigationBar.layoutIfNeeded()
override func viewWillDisappear(_ animated: Bool)
super.viewWillDisappear(true)
// 2. show the shadow image when pushing or popping in the next view controller. Only the shadow image will blink
navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
navigationController?.navigationBar.setValue(false, forKey: "hidesShadow")
navigationController?.navigationBar.layoutIfNeeded()
【讨论】:
【参考方案17】:如果只想去掉底线,保持navigationBar的纯色,在viewDidLoad中添加这几行代码: 斯威夫特 3、4:
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = false
和平!
【讨论】:
【参考方案18】:在您的自定义导航控制器中添加以下行:
self.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.layoutIfNeeded()
重要提示
如果您使用第一行 viewDidLoad() 方法,最后一行很重要,因为 navigationController 应该重绘导航栏,但您可以轻松地在 viewWillAppear() 方法中使用它而无需 layoutIfNeeded() 在它绘制导航栏之前
【讨论】:
【参考方案19】:在 AppDelegate 中,这已全局更改了 NavBar 的格式并移除了底线/边框:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
UINavigationBar.appearance().setBackgroundImage(UIImage(), forBarPosition: UIBarPosition.Any, barMetrics: UIBarMetrics.Default)
UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
UINavigationBar.appearance().barTintColor = UIColor.redColor()
UINavigationBar.appearance().translucent = false
UINavigationBar.appearance().clipsToBounds = false
//UINavigationBar.appearance().backgroundColor = UIColor.redColor()
UINavigationBar.appearance().titleTextAttributes = [NSFontAttributeName : (UIFont(name: "FONT NAME", size: 18))!, NSForegroundColorAttributeName: UIColor.whiteColor()]
没有设法在特定的 VC 上实现任何不同的东西,但这将帮助 90% 的人
【讨论】:
UINavigationBar.appearance().backgroundColor = UIColor.redColor() 不需要。【参考方案20】:对于 swift3,您应该以稍微不同的方式编写:
self.navigationController?.navigationBar.setBackgroundImage(UIImage(),
for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
【讨论】:
【参考方案21】:这是Gaurav Chandarana答案的精简版。
extension UINavigationBar
func hideShadow(_ value: Bool = true)
setValue(value, forKey: "hidesShadow")
【讨论】:
【参考方案22】:应用委托
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()
【讨论】:
【参考方案23】:边界线是一个 UIImageView,删除一个 imageView 的子视图将删除带有 UIImageView 的 barButtonItems。下面的代码将帮助您删除它。希望这对遇到像我这样的问题的人有所帮助。
for parent in self.navigationController!.navigationBar.subviews
for childView in parent.subviews
if childView.frame.height == 0.5
childView.removeFromSuperview()
边框 UIImageView 的高度只有 0.5,所以这段代码只删除了那个。
【讨论】:
这导致我崩溃。我认为 parent 和 childViews 需要在检查每个之前打开,以防它们为零。不过,我使用的是自定义 UINavigationController,因此对于具有标准栏的其他用户而言,情况可能并非如此。【参考方案24】:这是 Nate Cook 答案的 swift 3 base 中的答案
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
self.navigationController?.navigationBar.shadowImage = UIImage()
【讨论】:
【参考方案25】:iOS 11 和 Swift 4 如果你想移除边框但不要让导航栏半透明,你应该尝试跟随
self.navigationBar.shadowImage = UIImage()
【讨论】:
【参考方案26】:我在 AppDelegate 的 didFinishLaunchingWithOptions 方法中使用此代码在整个应用程序中访问它:
let barAppearance = UINavigationBar.appearance()
if #available(iOS 13, *)
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
barAppearance.standardAppearance = appearance
barAppearance.scrollEdgeAppearance = appearance
else
barAppearance.setBackgroundImage(UIImage(), for: UIBarPosition.any, barMetrics: UIBarMetrics.defaultPrompt)
barAppearance.shadowImage = UIImage()
【讨论】:
【参考方案27】:斯威夫特 11.4
我正在自定义 UINavigationController 所以通过self.navigationController?.navigationBar
访问对我不起作用,
但直接使用:
self.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.layoutIfNeeded()
【讨论】:
以上是关于如何快速删除导航栏的边框?的主要内容,如果未能解决你的问题,请参考以下文章