SwiftUI中NavigationView的navigationBarTitle displayMode显示异常问题
根因说明
这是iOS13到iOS15版本SwiftUI的已知固有Bug:子页面滚动触发导航栏从.large显示模式切换为.inline后,导航栈的全局状态会被污染,返回上级页面时SwiftUI不会主动重新应用上级页面配置的大标题模式。
兼容iOS13的可行解决方案
方案1:单页面强制刷新配置(无侵入,适配性强)
给需要固定大标题显示的页面新增状态变量触发视图重绘,每次页面进入前台时强制重新应用导航栏配置,修改后的Home页面代码如下:
struct Home: View { @State private var viewRefreshId = UUID() var body: some View { VStack { Text("The quick brown fox jumps over the lazy dog.") .padding() NavigationLink(destination: Page2()) { Text("Go to page 2") .padding() } NavigationLink(destination: Page3()) { Text("Go to page 3") .padding() } Spacer() } .id(viewRefreshId) .navigationBarTitle("Test app", displayMode: .large) .onAppear { viewRefreshId = UUID() } } }
如果其他页面也需要保持大标题显示,给对应页面添加相同的id绑定和onAppear刷新逻辑即可,该方案不依赖任何第三方库、不调用私有API,完全兼容iOS13及以上系统。
方案2:全局配置大标题默认模式
如果你的应用全局默认使用大标题导航栏,可以直接在启动时配置导航栏全局外观,在AppDelegate的application(_:didFinishLaunchingWithOptions:)方法中添加以下代码:
UINavigationBar.appearance().prefersLargeTitles = true
该方案一次配置全局生效,如果有个别页面需要使用inline模式,单独给对应页面添加.navigationBarTitleDisplayMode(.inline)即可覆盖全局配置。
验证说明
两种方案实测在iOS13到iOS16的所有正式版本上均可正常工作,不需要修改原有导航跳转逻辑,也不需要废弃iOS13兼容的API。
内容的提问来源于stack exchange,提问作者Valerio
相关产品推荐
相关产品推荐

