【问题标题】: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: "")

插图:

【问题讨论】:

    标签: ios iphone swift uinavigationbar


    【解决方案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()
                                

                                【讨论】:

                                  猜你喜欢
                                  • 1970-01-01
                                  • 2018-10-15
                                  • 1970-01-01
                                  • 2016-07-02
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2014-11-03
                                  相关资源
                                  最近更新 更多