簡體   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