iOS15下滚动视图从父视图移除时如何触发导航栏外观重绘?
问题原因
iOS 15+ 导航栏的外观规则如下:
- 视图层级存在UIScrollView时,滚动到顶部边缘使用
scrollEdgeAppearance配置,其余滚动位置使用standardAppearance配置 - 视图层级不存在UIScrollView时,默认全局使用
standardAppearance配置
你之前的操作仅修改了scrollEdgeAppearance且只调用了普通重绘方法,没有修改standardAppearance的配置,也没有触发导航栏重新读取外观配置的逻辑,所以无法生效。
解决方案
场景1:移除UIScrollView后不需要再恢复滚动切换导航栏样式的逻辑
直接将导航栏的两个外观属性都设为透明配置,再强制刷新导航栏状态即可:
// 移除UIScrollView后执行 let transparentAppearance = UINavigationBarAppearance() transparentAppearance.configureWithTransparentBackground() // 同时赋值两个外观属性,确保无ScrollView时也生效 navigationController?.navigationBar.standardAppearance = transparentAppearance navigationController?.navigationBar.scrollEdgeAppearance = transparentAppearance // 强制导航栏刷新渲染状态,比setNeedsDisplay生效更可靠 navigationController?.setNavigationBarHidden(true, animated: false) navigationController?.setNavigationBarHidden(false, animated: false)
场景2:后续需要把UIScrollView加回,要保留原来的滚动切换样式
先存储原始的standardAppearance,移除ScrollView时临时替换为透明配置,加回时再恢复:
// 首先在类中定义属性存储原始外观 var originalNavAppearance: UINavigationBarAppearance? // 移除UIScrollView时执行 originalNavAppearance = navigationController?.navigationBar.standardAppearance let transparentAppearance = UINavigationBarAppearance() transparentAppearance.configureWithTransparentBackground() navigationController?.navigationBar.standardAppearance = transparentAppearance // 强制刷新 navigationController?.setNavigationBarHidden(true, animated: false) navigationController?.setNavigationBarHidden(false, animated: false) // UIScrollView重新添加回视图层级时执行 if let original = originalNavAppearance { navigationController?.navigationBar.standardAppearance = original } // 强制刷新恢复滚动切换逻辑 navigationController?.setNavigationBarHidden(true, animated: false) navigationController?.setNavigationBarHidden(false, animated: false)
内容的提问来源于stack exchange,提问作者Jordan H
相关产品推荐
相关产品推荐

