Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
318 views
in Technique[技术] by (71.8m points)

iphone - Is there a way to programmatically scroll to a PDF page within a UIWebView?

It is possible to use JavaScript to set the pixel y-offset of a UIWebView, e.g.:

[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"scrollTo(0, %d)", offset]];

So is there a way to get:

  1. The pixel height of an individual page of a PDF within the web view?
  2. The size of the gap between pages?

Is this information available from the UIWebView or can it be calculated through alternative means?

I'm thinking that if I have the number of pages (via CGPDFDocumentGetNumberOfPages), the pixel height gap between pages, or the pixel height of an individual page, I can calculate the offset to use with the JavaScript call. Then I just wire up a UIButton or UISlider to move between pages.


EDIT I

I have a solution, but it uses UIWebDocumentView, a private subview of UIWebView.

I create a view controller called PDFViewerViewController, which is a subclass of WebViewerViewController, which itself is a view controller that contains a UIToolbar, a UIWebView, and conforms to the UIWebViewDelegate protocol.

My PDFViewerViewController calculates some information about the enclosing web view and the PDF data, after the web view delegate method -webViewDidFinishLoad: gets called.

This information is used to calculate an approximate per-page offset that gets fed to the web view via JavaScript.

PDFViewerViewController.h

#import <UIKit/UIKit.h>
#import "WebViewerViewController.h"

@interface UIWebDocumentView : NSObject {}
@end

@interface PDFViewerViewController : WebViewerViewController {
    NSUInteger offset;
    NSUInteger currentPage;
    NSUInteger documentPages;
    CGFloat documentHeight;
    CGFloat pageHeight;
}

@property (assign) NSUInteger offset;
@property (assign) NSUInteger currentPage;
@property (assign) NSUInteger documentPages;
@property (assign) CGFloat documentHeight;
@property (assign) CGFloat pageHeight;

@end

PDFViewerViewController.m

#import "PDFViewerViewController.h"

@implementation PDFViewerViewController

@synthesize offset;
@synthesize currentPage;
@synthesize documentPages;
@synthesize documentHeight;
@synthesize pageHeight;

- (void) viewDidLoad {
    [super viewDidLoad];

    UIBarButtonItem *_leftArrow = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"ArrowLeft.png"] style:UIBarButtonItemStylePlain target:self action:@selector(leftArrow:)];
    UIBarButtonItem *_flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
    UIBarButtonItem *_rightArrow = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"ArrowRight.png"] style:UIBarButtonItemStylePlain target:self action:@selector(rightArrow:)];
    [[super.viewerToolbarView toolbar] setItems:[NSArray arrayWithObjects:_leftArrow, _flexibleSpace, _rightArrow, nil]];
    [_leftArrow release];
    [_flexibleSpace release];
    [_rightArrow release];

    self.currentPage = 0;
}

- (void) webViewDidFinishLoad:(UIWebView *)_webView {
    for (UIView *_subview in [[[_webView subviews] objectAtIndex:0] subviews]) {
        if ([_subview isKindOfClass:[UIWebDocumentView class]]) {
            self.documentHeight = _subview.bounds.size.height;
        }
    }

    CGPDFDocumentRef pdfDocument = CGPDFDocumentCreateWithURL((CFURLRef)baseURL);
    self.documentPages = CGPDFDocumentGetNumberOfPages(pdfDocument);
    CGPDFDocumentRelease(pdfDocument);

    self.pageHeight = (self.documentHeight + (10 * self.documentPages)) / self.documentPages;
    self.currentPage = 1;
    self.offset = 0;
}

- (void) leftArrow:(id)_param {
    if (self.currentPage == 1) 
        return;
    self.offset -= (NSUInteger)self.pageHeight;
    self.currentPage--;
    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"scrollTo(0, %d)", (self.offset * 2)]];
}

- (void) rightArrow:(id)_param {
    if (self.currentPage == self.documentPages) 
        return;
    self.offset += (NSUInteger)self.pageHeight;
    self.currentPage++;
    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"scrollTo(0, %d)", (self.offset * 2)]];
}

Some observations

  1. The offset calculation isn't page-perfect. If the PDF document isn't 8.5 x 11 (e.g. A4) then the offset error gets worse more quickly.

  2. The self.currentPage property doesn't get updated when scrolling through the web view by way of touch-drag. One might drag a few pages, and then touching the left or right arrow on the toolbar will cause the offset to unexpectedly move to a previous page.

  3. This solution uses UIWebDocumentView, which is private and may likely cause app rejection.

I think I'll file a feature enhancement request with Apple.

Has anyone built a non-UIWebView-based PDF viewer (with source code)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So this post has been open for quite a while now but since it's the first entry on a Google search for "scroll pdf uiwebview" I thought I'd provide my take at this for future readers.

You can indeed scroll to a particular page in a PDF document using nothing but pure Java Script. I've posted sample code on our blog (http://apptech.next-munich.com/2011/02/pdf-in-uiwebview.html) but here's a short summary of what you need to do:

  1. Use the window.outerHeight DOM property to find the total height of the rendered PDF document.
  2. Use the window.innerHeight DOM property to find the height of the browser window in browser coordinates.
  3. Jump to the page using the window.scrollTo(x, y) function.

There is one catch, though, that you cannot just device the outerHeight by the number of pages and jump to what you get. Instead, you will have to multiply by the innerHeight/webView.bounds.size.height ratio.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...