如何在PDFKit中监听文档滚动至底部事件以解锁按钮?
滚动到PDF末尾解锁按钮的实现方案
核心思路
给PDFView设置代理监听滚动事件,判断用户是否滚动到文档最后一页的底部,同步更新SwiftUI中按钮的启用状态。
步骤1:修改PDFDocumentView,添加状态绑定
给UIViewRepresentable结构体添加@Binding属性传递按钮启用状态,并将代理与该绑定关联:
import PDFKit import SwiftUI struct PDFDocumentView: UIViewRepresentable { private var url: URL? @Binding var isButtonEnabled: Bool // 绑定按钮启用状态 private let pdfDocumentDelegate: PdfDocumentDelegate init(url: URL, isButtonEnabled: Binding<Bool>) { self.url = url self._isButtonEnabled = isButtonEnabled self.pdfDocumentDelegate = PdfDocumentDelegate(isButtonEnabled: isButtonEnabled) } func makeUIView(context: Context) -> PDFView { let pdfView = PDFView() pdfView.delegate = pdfDocumentDelegate // 设置代理 if let url { pdfView.document = PDFDocument(url: url) pdfView.autoScales = true pdfView.maxScaleFactor = 3.0 pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit } return pdfView } func updateUIView(_ uiView: PDFView, context: Context) {} }
步骤2:实现PDFView代理逻辑
完善PdfDocumentDelegate类,通过滚动监听判断是否到达文档末尾:
class PdfDocumentDelegate: NSObject, PDFViewDelegate { @Binding private var isButtonEnabled: Bool init(isButtonEnabled: Binding<Bool>) { self._isButtonEnabled = isButtonEnabled super.init() } func pdfViewDidScroll(_ pdfView: PDFView) { guard let document = pdfView.document else { return } let totalPages = document.pageCount guard let visiblePage = pdfView.currentPage else { return } let currentPageIndex = document.index(for: visiblePage) + 1 // 未到最后一页时保持按钮禁用 guard currentPageIndex == totalPages else { if isButtonEnabled { isButtonEnabled = false } return } // 计算当前页面可见区域是否到达底部 let pageBounds = visiblePage.bounds(for: pdfView.displayBox) let visibleRect = pdfView.convert(pdfView.bounds, to: visiblePage) // 留10pt误差避免滚动精度问题 let isAtBottom = visibleRect.maxY >= pageBounds.maxY - 10 if isAtBottom != isButtonEnabled { isButtonEnabled = isAtBottom } } }
步骤3:在主视图中使用
创建包含PDFView和按钮的SwiftUI视图,绑定状态控制按钮启用:
struct ContentView: View { @State private var buttonEnabled = false var body: some View { VStack { PDFDocumentView(url: yourPDFURL, isButtonEnabled: $buttonEnabled) .edgesIgnoringSafeArea(.all) Button("确认完成") { // 按钮点击逻辑 } .disabled(!buttonEnabled) .padding() .background(buttonEnabled ? Color.blue : Color.gray) .foregroundColor(.white) .cornerRadius(8) } } // 替换为你的PDF文件URL private var yourPDFURL: URL { guard let url = Bundle.main.url(forResource: "sample", withExtension: "pdf") else { fatalError("PDF文件不存在") } return url } }
关键说明
- 利用
@Binding实现SwiftUI与UIKit组件的状态双向同步。 - 通过
PDFViewDelegate的滚动监听方法,实时检查当前页面位置和可见区域。 - 设置10pt的误差阈值,避免因滚动时的微小偏移导致按钮状态频繁切换。
内容的提问来源于stack exchange,提问作者Konstantin.Efimenko
相关产品推荐
相关产品推荐

