繁体   English   中英

iOS PDFKit 调整 PDFView 中的 pdf 框架

[英]iOS PDFKit adjust pdf frame in PDFView

我有一个 PDF 具有不同高度的页面,我想以水平分页的方式显示,一次一页,页面之间没有间隙,并且每个页面的顶部与视图的顶部对齐。 例如:

所需的渲染

我想使用PDFKitPDFView ,特别是因为这些设置可以通过以下方式实现:

let pdfView = PDFView()
pdfView.displayDirection = .horizontal
pdfView.displaysPageBreaks = false
pdfView.usePageViewController(true, withViewOptions: nil)

但是,这会产生以下结果:

实际渲染

这是由于页面的高度不同。 每个页面在PDFView中垂直居中,如果页面的高度大于视图的高度(例如第 2 页),则按纵横比缩放以适应。

为了尝试解决第一个问题,垂直偏移,我尝试了几件事。 首先,这很严重,我知道这是错误的,在检查视图层次结构并找到页面呈现的私有视图(名为PDFTextInputView的 class 的视图)我尝试将其框架的origin.y调整为0时最外层的滚动视图(另一个私有视图)滚动。 这是因为每当下一页或上一页滚动到视图中时,页面都会呈现在视图的顶部。 但是,一旦用户在该页面上进行捏合缩放,它的框架就会自动跳回居中。 除了依赖私有视图层次结构之外,这种方法是行不通的。

为了尝试解决“高页面问题”(第 2 页),我尝试在出现新页面时调整 PDFView 的比例因子。 可悲的是, .PDFViewPageChanged通知仅在滚动视图结束减速触发,因此页面在滚动时被缩小,然后当我调整比例因子时它会跳转以适应屏幕的宽度。 然后我转向.PDFViewVisiblePagesChanged ,它会在下一个/上一个页面进入视图时触发(以及更多次,这很好),这与.PDFViewPageChanged有相同的问题。

我尝试过的其他事情:

  • 在文档视图上调整transform
  • 拦截捏合手势并调整文档视图的中心
  • 创建我自己的页面 controller 并每页呈现一个 PDF 页面(不使用pdfView.usePageViewController

有人对我如何实现我所追求的有任何想法吗?

新黑客:

所以事实证明,在挖掘了一些更多的私有 API(是的,这个解决方案仍然很恶心)之后,我在PDFScrollView (一个私有的内部视图)上完全忽略了这个神奇的属性,称为......

forcesTopAlignment

要启用此功能,请在您的PDFView PDFScrollView

pdfScrollView.setValue(true, forKey: "forcesTopAlignment")

这样就行了!


老黑客:

经过几天的努力,我终于找到了一种让PDFView表现出我想要的方式的方法。

披露:该解决方案使用方法混合并依赖于私有视图层次结构,并且可能随时中断。 也就是说,它现在有效,我对解决方案感到满意。

此要点中提供了完整的解决方案。 (肉在overrideCenterAlign 。)

有一个名为_centerAlign的私有方法,当 pdf 页面出现在屏幕上并使用捏合手势进行缩放时,它会垂直居中并缩放它们。 Swizzling 该方法允许我注入我自己的逻辑并将我自己的转换应用到 position pdf 查看我想要的方式(页面顶部与视图顶部对齐。)

有两种情况需要考虑。 “短页”案例(示例中的第 1、3、4 页)和“高页”案例(示例中的第 2 页)。在这两种情况下,我首先调用_centerAlign的原始实现,以便它可以应用它的转换和管理更新内部滚动视图。

  • 对于“短页”情况,我应用了相同的转换和垂直平移,以将 pdf 的顶部与视图的顶部对齐。
  • 对于“长页面”的情况,我调整内部滚动视图的缩放比例,因为它出现在屏幕上,以便缩放以适应视图的宽度。

综上所述,我对不依赖私有方法和视图层次结构的更清洁的解决方案持开放态度。 如果您知道实现此目的的更好方法,请发布答案!

只需将 forceTopAlignment 设置为 true

例子:

lazy var pdfView: PDFView = {
    let pdf = PDFView()
    pdf.displayMode = .singlePageContinuous
    pdf.autoScales = true
    pdf.translatesAutoresizingMaskIntoConstraints = false
    pdf.setValue(true, forKey: "forcesTopAlignment")
    return pdf
}()

我的答案与接受的答案有何不同?

pdfView 上没有可用的滚动视图属性。 因此,您只需将值直接设置为 pdfView。

我认为问题在于将 PDFView 添加到有约束的视图中。 当我只使用 addSubview() 和用户正确的框架添加时,它不需要调用 setValue。

让 pdfView = PDFKit.PDFView(frame: self.view.bounds) pdfView.document = PDFKit.PDFDocument(url: url) pdfView.autoresizingMask = [.flexibleHeight, .flexibleWidth] view.addSubview(pdfView)

注意:此答案旨在帮助其他到达这里尝试解决类似问题的人。

自从苹果在 iOS13 中引入“拖动隐藏”(Apple “https://developer.apple.com/design/human-interface-guidelines/ios/app-architecture/modality/”)以来,我在 iOS12 中发现了一个令人讨厌的错误。

如果目标是 iOS13 或更高版本,一切正常。

在 iOS12 中,可能是由于计算大小不同,(我猜..) pdf 呈现错误:某些内容 go 向右并被剪掉。

一个肮脏的修复包括不打电话

self?.pdfView.autoScales = true

在 viewDidLoad 中,

但是在加载每个 PDF 后等待一些毫秒并设置它:

 if #available(iOS 13.0, *) {
    // NADA.. go on..
 }else{
     self.pdfView.autoScales = false // disable it.
     self?.pdfView.alpha = 1
}


let pdf = load ....... 

self.pdfView.document = pdf

 if #available(iOS 13.0, *) {
        //nada..
        } else {
            // hack for ios 12
            let when = DispatchTime.now() + 0.25
            DispatchQueue.main.asyncAfter(deadline: when, execute: { [weak self] in
                self?.pdfView.autoScales = true // hack for ios 12
                self?.pdfView.alpha = 1
            })
        }
  

使用 alpha 防止查看 pdf 尚未采用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM