如何快速删除NavigationBar的边框?


131

我一直在尝试删除NavigationBars边框而没有运气。经过研究,人们似乎告诉我们将shadowImage和BackgroundImage设置为nil,但这在我的情况下不起作用。

我的密码

    self.navigationController?.navigationBar.barTintColor = UIColor(rgba: "#4a5866")
    self.navigationController?.navigationBar.setBackgroundImage(UIImage(named: ""), forBarMetrics: UIBarMetrics.Default)
    self.navigationController?.navigationBar.shadowImage = UIImage(named: "")

插图:

在此处输入图片说明

Answers:


309

问题在于这两行:

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()

2
这个答案确实有效。因为如果使用可接受的答案(代码),则将其删除工具栏的imageViews。
Sergey Krasiuk '16

1
这应该是公认的答案。从UINavigationBar.appearance()设置时也适用
Heinrisch

1
这应该是Swift 3的可接受答案。可接受的答案在Swift 2中对我
有用

1
对于swift3,您应该编写稍微不同的方式:self.navigationController?.navigationBar.setBackgroundImage(UIImage(),用于:UIBarMetrics.default)self.navigationController?.navigationBar.shadowImage = UIImage()
Chetan Dobariya

5
此方法与iOS 11中的大标题冲突
SteffenK '17

54

Swift 4和Swift 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()

2
完美答案:)
PJR

我们在这里需要layoutIfNeeded()吗?
korgx9 '19

1
是的,korgx9,我们需要它。否则,直到下一次绘制,它才会改变颜色。
Sazzad Hissain Khan

37

这将完全删除阴影图像

for parent in self.navigationController!.navigationBar.subviews {
 for childView in parent.subviews {
     if(childView is UIImageView) {
         childView.removeFromSuperview()
     }
 }
}

1
您能详细说明一下吗?
Kmeixner 2015年

1
对于我来说,也可以使用此解决方案,而@Nate Cook的答案无效。:S
卡·达万佐

2
神圣的女强人!经过所有搜索,这是唯一有效的方法。
Tuan Anh Vu 2015年

它的工作原理,但我在导航栏中有一个菜单图标,它消失了:/我只想删除边框。帮助:/
Stephy Samaniego,2016年

这对我有用,但是在推送新的ViewController之后,将其从那里删除了。我该如何防止呢?
Anirudha Mahale

36

使用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)

正确答案。
Ed

这是综合答案!
madeny

最好在Appdelegate编写这样有用的默认值,而不要在奇数处编写它们。正确答案:)
Md Rais

35

只需将其写在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上,那么这是最简单的方法
Lance Samaria

假设我们有一个包含5个viewControllers的viewControllers堆栈(并且我们已经在第一个中隐藏了阴影)。现在,仅对于第3个viewController,我不想隐藏阴影。因此,我将在第3个viewController的viewWillAppear中使用FALSE并在第3个viewController的viewWillDisappear中使用TRUE调用该方法。这就是全部!
Gaurav Chandarana

您绝对正确,思想很好!不要以为我回答了您的答案,因为它非常简洁有效,我也投了赞成票。我用它删除它和navBar以获得错误消息。我发现的问题是在vc1中删除它但将其显示为vc2时,但是如果vc2中存在错误,则在viewWillDisappear中删除它可能无法正常工作。但这又是一个非常独特的情况。我确实喜欢将viewWillDisappear想法用于一般情况,您应该将其添加到答案中。无论您的代码如何工作,这都是消除阴影的简便方法!👍🏿👍🏿
兰斯撒玛利亚

奇迹般有效。只是想确保这不是私人设置?
inokey

2
这是一个很好的答案!我添加了一个简化代码的答案。
Scott Gardner

13

设置barStyle.Black设置色调之前:

self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barStyle = .Black
self.navigationController?.navigationBar.barTintColor = UIColor.blueColor()

这真的有效吗?还是我想得太多?
2015年

@joe很好,它在这里工作:-)对您不起作用吗?
gpbl

就是这样,它确实起作用。我只是想知道,如果有一个解释,为什么打开barStyle黑色它然后转动整个barTintColor蓝:)

也许将其设置为黑色和不透明,它会关闭navigationBar中的某些图层/视图...
gpbl 2015年

我尝试使用它,但确实删除了底线,但是,如果使用白色的条形标题不可见:/
RileyDev

11

斯威夫特5

使用setBackgroundImage / shadowImage隐藏发际线时,会稍有延迟。此方法消除了延迟。感谢变色龙框架。这是他们使用的方法(在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
    }
}

1
FWIW,这是在iOS 13.4上对我
有用

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,因此此调用在任何地方都兼容。


不错,在导航时有什么方法可以显示/隐藏某些viewController中的阴影吗?
Ashkan.H,

您应该检查具有的高度height >= 1.0。在具有3倍视网膜屏幕的iPhone机型(例如8 Plus,XR ...)上,发际线的高度为0.33。
fl034

7

要从Swift 3+中的UINavigationBar移除边框,请使用:

UINavigationBar.appearance().shadowImage = UIImage()
UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
UINavigationBar.appearance().isTranslucent = false

5

迅速3

viewDidLoad方法

navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()


4

为Swift 4更新,以防有人怀疑

navigationBar.shadowImage = UIImage()
navigationBar.backIndicatorImage = UIImage()

现在它不再那么冗长。


2

如果您想在不更改背景颜色的情况下执行以下操作:

// 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不希望其视图消失


2

接受的答案对我有用,但是当我弹出或向前推到另一个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()
}

1

对于swift3,您应该编写略有不同的方式:

 self.navigationController?.navigationBar.setBackgroundImage(UIImage(),
    for: UIBarMetrics.default)
   self.navigationController?.navigationBar.shadowImage = UIImage()


1

应用委托

UINavigationBar.appearance().setBackgroundImage(UIImage(), for: UIBarMetrics.default)
UINavigationBar.appearance().shadowImage = UIImage()

1

如果您只想删除最底行并保持navigationBar的纯色,请在viewDidLoad中添加以下代码行:Swift 3,4:

navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.isTranslucent = false

和平!


0

边界线是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和childView需要在检查每个对象之前为零的情况下进行包装。我虽然使用了自定义UINavigationController,所以对于其他使用标准栏的用户而言,情况可能并非如此。
Natalia

0

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()。
萨比兰

0

这是Nate Cook的迅速3基础答案

   self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
    self.navigationController?.navigationBar.shadowImage = UIImage()

0

iOS 11和Swift 4如果要删除边框但不要使导航栏变得半透明,则应尝试执行以下操作
self.navigationBar.shadowImage = UIImage()


0

在您的自定义navigationController中,添加以下行:

self.navigationBar.setBackgroundImage(UIImage(), for:.default)
self.navigationBar.shadowImage = UIImage()
self.navigationBar.layoutIfNeeded()

重要的提示

如果您使用第一行viewDidLoad()方法,那么最后一行很重要,因为navigationController应该重绘导航栏,但在绘制导航栏之前,可以轻松地在viewWillAppear()方法中使用没有layoutIfNeeded()的方法


0

杰克·陈的快速方法:

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
    }

0
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithTransparentBackground()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.