如何快速删除导航栏的边框?

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 &gt;= 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()

【讨论】:

以上是关于如何快速删除导航栏的边框?的主要内容,如果未能解决你的问题,请参考以下文章

移除少数视图控制器的导航栏边框

如何从导航栏的 Highstock 图表中删除时间?

如何使用 JavaScript 在我的 HTML 导航栏的各个部分添加和删除活动类?

以编程方式快速更改导航栏的高度

在视图控制器中重置导航栏的外观

使用底部导航时删除应用栏的后退按钮 - 颤动