Swift切换导航栏颜色时出现绿色残影问题求助
解决导航栏返回时的颜色残影问题
这个问题我之前也碰到过,残影出现的核心原因是导航栏样式的切换时机和页面过渡动画冲突,或者View2中设置导航栏的动画在返回时还在影响过渡效果。下面给你几个能彻底解决的方案:
方案1:在View2消失前重置导航栏样式
最简单直接的方法,就是在View2即将消失的时候,提前把导航栏样式恢复成View1的样子,这样返回过渡时就不会出现绿色残影了。
在View2中添加viewWillDisappear方法:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 重置为View1的导航栏样式 self.navigationController?.navigationBar.isTranslucent = false self.navigationController?.navigationBar.barTintColor = UIColor(hexString: "#FFFFFF") self.navigationController?.navigationBar.shadowImage = nil // 恢复默认阴影(如果View1不需要自定义阴影的话) self.setStatusBarBackgroundColor(color: UIColor(hexString: "#FFFFFF")) }
说明:
这样做相当于在View2退出视野前,就把导航栏颜色切回白色,页面过渡动画开始时导航栏已经是正确的颜色,自然不会出现残影。记得要调用super.viewWillDisappear(animated),避免破坏系统的生命周期流程。
方案2:用导航控制器代理统一管理样式
如果你的项目中有多个页面需要切换导航栏样式,推荐用这种方法,统一控制样式切换时机,避免每个页面单独设置带来的冲突。
- 让导航控制器的代理(比如View1或者专门的代理类)遵守
UINavigationControllerDelegate协议 - 实现
navigationController(_:willShow:animated:)方法:
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { // 根据即将显示的页面设置对应的导航栏样式 if viewController is View1 { navigationController.navigationBar.isTranslucent = false navigationController.navigationBar.barTintColor = UIColor(hexString: "#FFFFFF") navigationController.navigationBar.shadowImage = nil setStatusBarBackgroundColor(color: UIColor(hexString: "#FFFFFF")) // 设置View1的标题视图和返回按钮隐藏 viewController.navigationItem.titleView = UIImageView(image: UIImage(named: "navBardTitleLogoBG")) viewController.navigationItem.hidesBackButton = true } else if viewController is View2 { navigationController.navigationBar.isTranslucent = false navigationController.navigationBar.barTintColor = UIColor(hexString: "#14B80E") navigationController.navigationBar.shadowImage = UIImage() setStatusBarBackgroundColor(color: UIColor(hexString: "#14B80E")) // 设置View2的标题 viewController.navigationItem.title = "Recipe Book" viewController.navigationItem.hidesBackButton = false } }
- 记得设置导航控制器的代理,比如在View1的
viewDidLoad中添加:
override func viewDidLoad() { super.viewDidLoad() self.navigationController?.delegate = self }
说明:
这个方法会在页面即将显示(不管是push还是pop)的时候,提前设置好导航栏样式,完全避免了样式切换时机不对的问题,是最稳妥的方案。同时要记得删除View1和View2中viewWillAppear里的导航栏设置代码,避免重复设置导致冲突。
额外提示:
你在View2的viewWillAppear中用UIView.animate包裹导航栏设置其实没必要——barTintColor的变化默认会跟随页面过渡动画,手动添加动画反而可能和系统过渡动画冲突,这也是残影出现的一个潜在原因。如果需要自定义动画时长,可以考虑用CATransaction来控制,而不是直接包UIView.animate。
内容的提问来源于stack exchange,提问作者Jobins John
相关产品推荐
相关产品推荐

