You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 12:06:20