PDFview scrolls to bottom of the page in single page document

6.4k Views Asked by At

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?

9

There are 9 best solutions below

3
On BEST ANSWER

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.

0
On
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.

0
On

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];
3
On

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)
}
2
On

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

0
On

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

1
On

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)
0
On

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];
}
1
On

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

if let scrollView = pdfView.subviews.first as? UIScrollView {
    scrollView.contentOffset.y = 0.0
}