如何禁用iPad上NavigationSplitView侧边栏的滑出交互?
问题
在iPad端的NavigationSplitView中,详情视图包含一个启用了pageViewController的PDFView(通过UIViewRepresentable实现),已设置columnVisibility初始值为.all,且配有控制侧边栏显示的按钮。但侧边栏默认的滑动呼出行为干扰了PDF反向翻页,在多页PDF末尾反向滑动时,常会触发侧边栏滑出而非翻页,行为不一致。请问能否禁用NavigationSplitView侧边栏的滑动呼出功能?
示例代码:
import SwiftUI import PDFKit enum Detail: Hashable { case pdfView case anotherView } struct ContentView: View { @State private var selection: Detail? @State private var columnVisibility = NavigationSplitViewVisibility.all var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { List(selection: $selection) { Section { NavigationLink(value: Detail.pdfView) { HStack(spacing: 12) { Image(systemName: "scroll") Text("PDF View") } } NavigationLink(value: Detail.anotherView) { HStack(spacing: 12) { Image(systemName: "info.circle") Text("Another View") } } } } } detail: { if selection == .pdfView { if let url = Bundle.main.url(forResource: "example", withExtension: "pdf") { PDFKitView(url: url) } else { EmptyView() } } else { Text("Another View") } } .navigationSplitViewStyle(.balanced) } } struct PDFKitView: UIViewRepresentable { let url: URL func makeUIView(context: UIViewRepresentableContext<PDFKitView>) -> PDFKitView.UIViewType { let pdfView = PDFView() pdfView.document = PDFDocument(url: self.url) pdfView.autoScales = true pdfView.displayMode = .singlePage pdfView.displayDirection = .horizontal pdfView.usePageViewController(true) return pdfView } func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PDFKitView>) { } }
解决方案
可以通过手势拦截或优先级调整来解决这个冲突,以下是两种实用方案:
方案一:全局禁用侧边栏滑动呼出
给NavigationSplitView添加全屏透明手势,优先拦截横向滑动,阻止侧边栏的触发手势。此方案下用户只能通过按钮控制侧边栏显示:
struct ContentView: View { @State private var selection: Detail? @State private var columnVisibility = NavigationSplitViewVisibility.all var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { List(selection: $selection) { Section { NavigationLink(value: Detail.pdfView) { HStack(spacing: 12) { Image(systemName: "scroll") Text("PDF View") } } NavigationLink(value: Detail.anotherView) { HStack(spacing: 12) { Image(systemName: "info.circle") Text("Another View") } } } } } detail: { if selection == .pdfView { if let url = Bundle.main.url(forResource: "example", withExtension: "pdf") { PDFKitView(url: url) } else { EmptyView() } } else { Text("Another View") } } .navigationSplitViewStyle(.balanced) // 添加全屏手势拦截侧边栏滑动 .overlay( Color.clear .contentShape(Rectangle()) .gesture( DragGesture(minimumDistance: 10) .onChanged { _ in } ) ) } }
方案二:仅在PDFView页面禁用侧边栏滑动
针对PDFView的pageViewController调整手势优先级,让PDF翻页手势优先响应,其他页面仍保留侧边栏滑动功能,更精准灵活:
struct PDFKitView: UIViewRepresentable { let url: URL func makeUIView(context: UIViewRepresentableContext<PDFKitView>) -> PDFView { let pdfView = PDFView() pdfView.document = PDFDocument(url: self.url) pdfView.autoScales = true pdfView.displayMode = .singlePage pdfView.displayDirection = .horizontal pdfView.usePageViewController(true) // 获取pageViewController的手势,提高优先级 if let pageVC = pdfView.pageViewController { for gesture in pageVC.view.gestureRecognizers ?? [] { gesture.cancelsTouchesInView = true gesture.priority = .defaultHigh } } return pdfView } func updateUIView(_ uiView: PDFView, context: UIViewRepresentableContext<PDFKitView>) { // 如需在更新时调整手势,可在此处理 } }
内容的提问来源于stack exchange,提问作者alionthego
相关产品推荐
相关产品推荐

