SwiftUI导航栏高度异常:如何将View3导航栏设为inline高度?
SwiftUI 导航栏高度异常问题解决方案
问题描述
必须在View 2中使用大标题(navigationBarTitleDisplayMode = .large)和.searchable修饰符,但跳转至View 3后,其导航栏高度出现异常——推测View 2的导航栏与搜索栏的高度总和被延续到了View 3中,需要将View 3的导航栏高度恢复为.inline显示模式下的正常高度。
代码示例
import SwiftUI struct ContentView: View { init() { let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = UIColor.red UINavigationBar.appearance().standardAppearance = appearance UINavigationBar.appearance().compactAppearance = appearance UINavigationBar.appearance().scrollEdgeAppearance = appearance } var body: some View { NavigationView { ScrollView { VStack { NavigationLink("View 2") { SecondView() } } } .navigationTitle("View 1") .navigationBarTitleDisplayMode(.large) } } } struct SecondView: View { @State var text = "" var body: some View { ScrollView { VStack { NavigationLink("View 3") { ThirdView() } } } .navigationTitle("View 2") .navigationBarTitleDisplayMode(.large) .searchable(text: $text) } } struct ThirdView: View { var body: some View { Text("View 3") .navigationTitle("View 3") .navigationBarTitleDisplayMode(.inline) } }
异常效果
{: width="300"}
解决方案
方案1:重置导航栏外观并强制更新布局
在View 3的onAppear回调中重新设置导航栏外观,并强制触发布局更新,让导航栏恢复到.inline模式的正常高度:
struct ThirdView: View { var body: some View { Text("View 3") .navigationTitle("View 3") .navigationBarTitleDisplayMode(.inline) .onAppear { // 同步全局导航栏配置 let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = UIColor.red UINavigationBar.appearance().standardAppearance = appearance UINavigationBar.appearance().compactAppearance = appearance UINavigationBar.appearance().scrollEdgeAppearance = appearance // 延迟执行布局更新,确保状态生效 DispatchQueue.main.async { UIApplication.shared.windows.first?.rootViewController?.view.setNeedsLayout() } } } }
方案2:使用新的NavigationStack(iOS 16+)
如果你的项目支持iOS 16及以上版本,建议用NavigationStack替代旧的NavigationView,新导航栈对导航栏状态的管理更稳定,可自动避免这类高度异常问题:
// 修改ContentView中的导航容器 struct ContentView: View { init() { // 保持原有导航栏外观配置不变 let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() appearance.backgroundColor = UIColor.red UINavigationBar.appearance().standardAppearance = appearance UINavigationBar.appearance().compactAppearance = appearance UINavigationBar.appearance().scrollEdgeAppearance = appearance } var body: some View { NavigationStack { // 替换为NavigationStack ScrollView { VStack { NavigationLink("View 2") { SecondView() } } } .navigationTitle("View 1") .navigationBarTitleDisplayMode(.large) } } }
内容的提问来源于stack exchange,提问作者bwJeong
相关产品推荐
相关产品推荐

