SwiftUI隐藏导航栏后,如何调整Refresh Control避免被自定义导航栏遮挡?
问题:自定义导航栏遮挡List的Refresh Control,如何调整位置?
隐藏系统导航栏后,自定义导航栏遮挡了List的Refresh Control,请问该如何调整Refresh Control的位置?
相关代码
ContentView代码
import SwiftUI struct ContentView: View { var body: some View { NavigationView { HomeNavigationBarView { List { NavigationLink { EmptyView() } label: { Text("Hello, world!") } } .listStyle(.insetGrouped) .refreshable { } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
自定义导航栏代码
struct HomeNavigationBarView<Content: View>: View { let content: () -> Content var body: some View { ZStack(alignment: .top) { content() HStack { Image("logo") .resizable() .frame(width: 44, height: 44) } .frame(height: insetTop(), alignment: .bottom) .frame(maxWidth: .infinity) .background(.red.opacity(0.1)) } .navigationBarHidden(true) } } private func insetTop() -> CGFloat { let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene let window = windowScene?.windows.first return window?.safeAreaInsets.top ?? 0 // 20或47 }
问题截图

解决方法
问题根源是自定义导航栏通过ZStack叠加在List上方,且导航栏背景覆盖了系统安全区顶部(safeAreaTop),而List的Refresh Control默认显示在该区域,导致被遮挡。以下是两种可行的解决方案:
方案一:调整导航栏布局,避免覆盖安全区顶部
修改自定义导航栏的布局,让导航栏背景仅覆盖自身内容区域,不占用安全区顶部空间。这样Refresh Control可以正常显示在安全区顶部,不会被遮挡。
修改后的自定义导航栏代码:
struct HomeNavigationBarView<Content: View>: View { let content: () -> Content var body: some View { ZStack(alignment: .top) { content() HStack { Image("logo") .resizable() .frame(width: 44, height: 44) } .frame(height: 44) // 固定导航栏内容高度为44 .frame(maxWidth: .infinity) .background(.red.opacity(0.1)) .padding(.top, insetTop()) // 将导航栏内容下移至安全区顶部下方 } .navigationBarHidden(true) } } private func insetTop() -> CGFloat { let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene let window = windowScene?.windows.first return window?.safeAreaInsets.top ?? 0 }
方案二:给List添加顶部内边距,避开导航栏区域
通过给List添加顶部内边距,让滚动内容下移至导航栏下方,下拉时Refresh Control会显示在导航栏下方的区域,避免被遮挡。
修改后的自定义导航栏代码:
struct HomeNavigationBarView<Content: View>: View { let content: () -> Content var body: some View { ZStack(alignment: .top) { content() .padding(.top, navigationBarTotalHeight()) // 添加顶部内边距,避开导航栏 HStack { Image("logo") .resizable() .frame(width: 44, height: 44) } .frame(height: insetTop(), alignment: .bottom) .frame(maxWidth: .infinity) .background(.red.opacity(0.1)) } .navigationBarHidden(true) } private func navigationBarTotalHeight() -> CGFloat { insetTop() + 44 // 导航栏总高度 = 安全区顶部高度 + 内容高度 } } private func insetTop() -> CGFloat { let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene let window = windowScene?.windows.first return window?.safeAreaInsets.top ?? 0 }
推荐方案一,因为它保留了系统默认的Refresh Control位置逻辑,用户交互更符合iOS设计规范。
内容的提问来源于stack exchange,提问作者gaohomway
相关产品推荐
相关产品推荐

