iOS13+Swift5移除UINavigationBar底线阴影且保留导航栏颜色
我完全懂你的困扰——iOS 13之前那套移除导航栏阴影的代码,放到Swift 5环境里居然把导航栏颜色搞没了,明明已经设置了背景色还禁用了半透明对吧?
这是因为iOS 13之后苹果重构了UINavigationBar的样式配置逻辑,原来的旧API和新的UINavigationBarAppearance机制冲突了。直接设置backgroundImage为空会覆盖掉你设置的背景色,导致导航栏变成透明。
推荐解决方案:使用UINavigationBarAppearance(iOS 13+官方推荐)
这个API能精准控制导航栏的每一部分样式,既可以移除阴影,又能完美保留背景色,不管是全局配置还是单个导航控制器都适用。
1. 全局配置(所有导航栏生效)
在AppDelegate的application(_:didFinishLaunchingWithOptions:)里,或者SceneDelegate的scene(_:willConnectTo:options:)里添加以下代码:
// 创建导航栏样式实例 let navigationBarAppearance = UINavigationBarAppearance() // 设置你需要的导航栏背景色 navigationBarAppearance.backgroundColor = .systemBlue // 替换成你的目标颜色 // 移除底线和阴影:直接将阴影颜色设为透明 navigationBarAppearance.shadowColor = .clear // 也可以用这个方式移除阴影,效果一致: // navigationBarAppearance.shadowImage = UIImage() // 将样式应用到导航栏的各种状态 UINavigationBar.appearance().standardAppearance = navigationBarAppearance UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance // 适配滚动到顶部的状态 UINavigationBar.appearance().compactAppearance = navigationBarAppearance // 适配紧凑布局(比如iPhone横屏) // 确保禁用半透明(如果你需要的话) UINavigationBar.appearance().isTranslucent = false
2. 单个导航控制器配置(仅特定页面生效)
如果只想给某个导航控制器设置这个样式,直接在对应的ViewController里添加:
override func viewDidLoad() { super.viewDidLoad() let appearance = UINavigationBarAppearance() appearance.backgroundColor = .systemBlue appearance.shadowColor = .clear navigationController?.navigationBar.standardAppearance = appearance navigationController?.navigationBar.scrollEdgeAppearance = appearance navigationController?.navigationBar.isTranslucent = false }
为什么旧代码失效了?
iOS 13之前,导航栏的背景色由barTintColor控制,设置backgroundImage = UIImage()和shadowImage = UIImage()只会移除阴影,不会影响背景色显示。但iOS 13之后,导航栏的背景渲染逻辑改成了由UINavigationBarAppearance的backgroundColor主导,旧的setBackgroundImage(_:for:)方法会直接覆盖这个背景配置,导致你设置的颜色无法显示。
兼容旧版本(可选)
如果你的APP需要兼容iOS 12及以下,可以加个版本判断:
if #available(iOS 13.0, *) { // 上面的UINavigationBarAppearance代码 } else { // 旧版本的代码 UINavigationBar.appearance().barTintColor = .systemBlue UINavigationBar.appearance().shadowImage = UIImage() UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default) UINavigationBar.appearance().isTranslucent = false }
内容的提问来源于stack exchange,提问作者Jam Ku

