iOS返回根视图控制器时Large Navigation Bar背景变透明问题
看起来你遇到的这个问题在iOS 11+的大标题导航栏场景里挺常见的,主要是大标题导航栏的内部视图层级和过渡动画特性导致的,直接设置backgroundColor有时候会在滑动返回过程中失效。我来帮你分析下原因和对应的解决方案:
可能的问题根源
- iOS 11+的大标题导航栏(开启
prefersLargeTitles = true)有独立的背景视图层级,直接设置navigationBar.backgroundColor在过渡动画时无法稳定维持状态 - 导航栏默认的
isTranslucent属性为true,半透明状态下滑动时会和底层视图混合,视觉上呈现出背景变透明的效果 - 设置时机的覆盖不足,仅在
viewWillAppear和viewDidLoad设置,没覆盖到过渡动画过程中的状态变化
具体解决方案
1. 改用官方推荐的barTintColor设置背景色
UIKit专门为导航栏设计了barTintColor属性来设置背景色,相比直接设置backgroundColor,它能更好地适配大标题导航栏的视图层级:
func largeNavigationTitle() { // 统一导航控制器view的背景色,避免滑动时露出底层违和颜色 self.navigationController?.view.backgroundColor = VVUtility.splashBackGroundColor() let productTitle = request?.product?.name self.navigationItem.title = "\(productTitle ?? " ")".localized() // 设置普通标题的文字属性 self.navigationController?.navigationBar.titleTextAttributes = [ NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : VVUtility.normalFontWithPlusSize(increaseSize: -2.0) ] if #available(iOS 11.0, *) { self.navigationController?.navigationBar.prefersLargeTitles = true // 替换为barTintColor设置背景色 self.navigationController?.navigationBar.barTintColor = VVUtility.splashBackGroundColor() // 禁用半透明,避免过渡时的视图混合问题 self.navigationController?.navigationBar.isTranslucent = false self.navigationController?.navigationBar.largeTitleTextAttributes = [ NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : VVUtility.normalFontWithPlusSize(increaseSize: 0.0) ] } else { // iOS 11以下的兼容设置 self.navigationController?.navigationBar.barTintColor = VVUtility.splashBackGroundColor() self.navigationController?.navigationBar.isTranslucent = false } }
2. 可选:在viewWillDisappear中巩固状态
如果滑动返回时仍有异常,可以在当前视图控制器的viewWillDisappear中再次确认导航栏设置,避免返回时状态被重置:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) let bgColor = VVUtility.splashBackGroundColor() self.navigationController?.navigationBar.barTintColor = bgColor self.navigationController?.navigationBar.isTranslucent = false }
3. 可选:全局统一导航栏样式
如果APP内多个页面都使用大标题导航栏,可以在App启动时全局设置,避免重复设置导致的状态不一致:
// 在AppDelegate或SceneDelegate的启动方法中添加 UINavigationBar.appearance().barTintColor = VVUtility.splashBackGroundColor() UINavigationBar.appearance().isTranslucent = false if #available(iOS 11.0, *) { UINavigationBar.appearance().prefersLargeTitles = true UINavigationBar.appearance().largeTitleTextAttributes = [ NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : VVUtility.normalFontWithPlusSize(increaseSize: 0.0) ] } UINavigationBar.appearance().titleTextAttributes = [ NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font : VVUtility.normalFontWithPlusSize(increaseSize: -2.0) ]
方案说明
barTintColor会正确作用于导航栏的所有背景视图层级,包括大标题模式下的扩展背景区域,避免过渡动画中的状态丢失- 禁用
isTranslucent后,导航栏完全不透明,滑动时不会和底层视图混合,彻底解决背景变透明的视觉问题 - 统一导航控制器view的背景色,就算过渡时导航栏有短暂层级变化,底层颜色也和导航栏一致,不会露出违和的色块
你可以先尝试第一种方案,应该就能解决滑动返回时背景变透明的问题了。
内容的提问来源于stack exchange,提问作者Omid Kia
相关产品推荐
相关产品推荐

