PDFview scrolls to bottom of the page in single page document
Asked Answered
A

9

18

I am creating a PDFViewer application. I have set the autoScale Property of the PDFViewer to true, so that it the view expands to the width of the screen. Works fine with large PDF documents. But when the document is a single page document, the page automatically scrolls down to the end of the page, instead of starting with the beginning. I just cant understand the root cause of it. What am I missing here?

Avaavadavat answered 26/11, 2014 at 11:20 Comment(0)
N
8

I think this is a bug in PDFView.

As workaround I suggest to manually scroll top the top:

self.pdfView.document = pdfDocument;

NSPoint pt = NSMakePoint(0.0, [self.pdfView.documentView bounds].size.height);
[self.pdfView.documentView scrollPoint:pt];

Bug Reporter

rdar://37942090: PDFview scrolls to bottom of the page in single page document.

Nariko answered 5/12, 2014 at 4:18 Comment(3)
I find the bug still exits, do you know how to implement it in iOS11?Dappled
PDFKit on iOS doesn't give access to the underlaying UIScrollView. But try this message: - (void)goToRect:(PDFRect)rect onPage:(PDFPage *)page; ... I assume CGRectMake(0,0,1,1) may workNariko
No visible @interface for 'UIView' declares the selector 'scrollPoint:'Superhuman
L
9

This is what I did, it's a bit hacky

if let scrollView = pdfView.subviews.first as? UIScrollView {
    scrollView.contentOffset.y = 0.0
}
Latricelatricia answered 5/6, 2019 at 19:12 Comment(1)
In case you want to scroll to the view's top, which includes the page's shadow, this seems to be the way to go, as the other answers scroll to the top of the page, so that the top shadow isn't visible.Cobden
N
8

I think this is a bug in PDFView.

As workaround I suggest to manually scroll top the top:

self.pdfView.document = pdfDocument;

NSPoint pt = NSMakePoint(0.0, [self.pdfView.documentView bounds].size.height);
[self.pdfView.documentView scrollPoint:pt];

Bug Reporter

rdar://37942090: PDFview scrolls to bottom of the page in single page document.

Nariko answered 5/12, 2014 at 4:18 Comment(3)
I find the bug still exits, do you know how to implement it in iOS11?Dappled
PDFKit on iOS doesn't give access to the underlaying UIScrollView. But try this message: - (void)goToRect:(PDFRect)rect onPage:(PDFPage *)page; ... I assume CGRectMake(0,0,1,1) may workNariko
No visible @interface for 'UIView' declares the selector 'scrollPoint:'Superhuman
H
8

I propose this solution for scrolling to top of first page (it works on iOS 11.3):

if let document = pdfView.document,
   let firstPage = document.page(at: 0)
{
    let firstPageBounds = firstPage.bounds(for: pdfView.displayBox)
    pdfView.go(to: CGRect(x: 0, y: firstPageBounds.height, width: 1.0, height: 1.0), on: firstPage)
}
Hobnailed answered 5/5, 2018 at 7:16 Comment(3)
This was close but didn't work quite right on rotated and/or cropped pages. I posted my modification below.Heifetz
This doesn't seem to be working with pdfView.autoScale = true. The pdf always opens at the bottom of the second pageCoast
Yes, this solution works (autoScale doesn't matter) and it scrolls to the top of the page. But in case you want to scroll a little bit further as a user would be able to do (so that the page's top shadow is visible), @aaron-halvorsen's anwser seems to be the way to go.Cobden
P
6

Looks like the go command needs to be done on the next run through the run loop to work reliably:

DispatchQueue.main.async
{
    guard let firstPage = pdfView.document?.page(at: 0) else { return }
    pdfView.go(to: CGRect(x: 0, y: Int.max, width: 0, height: 0), on: firstPage)
}

Tested on iOS 12

Plectrum answered 16/4, 2019 at 18:43 Comment(0)
H
4

Expanding on Petro's answer, I had some issues with rotated pages and cropped pages, but this seems to work universally. I actually tested it on rotated pages, along with an annotation in the corner to verify that I was selecting the right corner:

     guard let firstPage = pdfView!.document?.page(at: 0) else {
        return;
     }
     let firstPageBounds = firstPage.bounds(for: pdfView!.displayBox)
     switch (firstPage.rotation % 360) {
     case 0:
        topLeftX = firstPageBounds.minX
        topLeftY = firstPageBounds.maxY
     case 90:
        topLeftX = firstPageBounds.minX
        topLeftY = firstPageBounds.minY
     case 180:
        topLeftX = firstPageBounds.maxX
        topLeftY = firstPageBounds.minY
     case 270:
        topLeftX = firstPageBounds.maxX
        topLeftY = firstPageBounds.maxY
     default:
        print ("Invalid rotation value, not divisible by 90")
     }

     pdfView!.go(to: CGRect(x: topLeftX, y: topLeftY, width: 1.0, height: 1.0), on: firstPage)
Heifetz answered 9/7, 2018 at 20:22 Comment(1)
Awesome solution; worked for me in viewDidLayoutSubviews()Gallstone
T
4

I was loading the document in viewDidLoad, then I moved it to viewDidAppear, and it worked for me.

Turnabout answered 8/7, 2019 at 8:35 Comment(2)
Good one. viewDidLoad does not seem to be the right place for modifying screen content, because layouts have not been processed yet... No need to set any offsets or frames on PDFView, when you first set its document in viewDidAppearMelisenda
Thank you! This was a very important piece of information.Blanding
S
1

The rotation of the PDFPage matters! This is the Objective-C version of Oded:

- (void)scrollToTopOfPage:(PDFPage *)page {
    CGRect pageBounds = [page boundsForBox:self.displayBox];
    CGFloat topLeftX = 0;
    CGFloat topLeftY = 0;
    switch (page.rotation % 360) {
        case 0:
            topLeftX = CGRectGetMinX(pageBounds);
            topLeftY = CGRectGetMaxY(pageBounds);
            break;
        case 90:
            topLeftX = CGRectGetMinX(pageBounds);
            topLeftY = CGRectGetMinY(pageBounds);
            break;
        case 180:
            topLeftX = CGRectGetMaxX(pageBounds);
            topLeftY = CGRectGetMinY(pageBounds);
            break;
        case 270:
            topLeftX = CGRectGetMaxX(pageBounds);
            topLeftY = CGRectGetMaxY(pageBounds);
            break;
        default:
            break;
    }

    [self goToRect:CGRectMake(topLeftX, topLeftY, 1, 1) onPage:page];
}
Sisley answered 24/1, 2020 at 23:56 Comment(0)
C
1
if let document = PDFDocument(url: viewModel.url) {
        pdfView.document = document
        
        // avoid iOS autoscale issue
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
            self?.pdfView.autoScales = true
        }
    }

I used the work around to define the autoScales property a bit after the loading of the document. The first page is nicely fit on top then.

Carniola answered 21/5, 2021 at 9:3 Comment(0)
S
0

For Objective-C use:

PDFPage *firstPage = [pdfView.document pageAtIndex:0];
CGRect firstPageBounds = [firstPage boundsForBox:pdfView.displayBox];
[pdfView goToRect:CGRectMake(0, firstPageBounds.size.height, 1, 1) onPage:firstPage];
Strongarm answered 23/8, 2019 at 9:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.