【问题标题】:Is there a way to programmatically scroll to a PDF page within a UIWebView?有没有办法以编程方式滚动到 UIWebView 中的 PDF 页面?
【发布时间】:2009-12-18 12:06:32
【问题描述】:

可以使用 JavaScript 设置UIWebView 的像素 y 偏移量,例如:

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

那么有没有办法得到:

  1. Web 视图中 PDF 单个页面的像素高度?
  2. 页面之间的间隙大小?

这些信息可以从UIWebView 获得还是可以通过其他方式计算?

我在想,如果我有页面数(通过 CGPDFDocumentGetNumberOfPages)、页面之间的像素高度差距或单个页面的像素高度,我可以计算 offset 以与 JavaScript 一起使用称呼。然后我只需连接一个UIButtonUISlider 在页面之间移动。


编辑我

我有一个解决方案,但它使用UIWebDocumentViewUIWebView 的私有子视图。

我创建了一个名为PDFViewerViewController的视图控制器,它是WebViewerViewController的子类,它本身就是一个包含UIToolbarUIWebView的视图控制器,并且符合UIWebViewDelegate协议。

在调用 Web 视图委托方法 -webViewDidFinishLoad: 后,我的 PDFViewerViewController 计算有关封闭 Web 视图和 PDF 数据的一些信息。

此信息用于计算通过 JavaScript 提供给 Web 视图的近似每页偏移量。

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)]];
}

一些观察

  1. 偏移量计算不是完美的页面。如果 PDF 文档不是 8.5 x 11(例如 A4),那么偏移误差会更快地恶化。

  2. 通过触摸拖动滚动浏览 Web 视图时,self.currentPage 属性不会更新。可能会拖几页,然后触摸工具栏上的左箭头或右箭头会导致偏移量意外移动到上一页。

  3. 此解决方案使用UIWebDocumentView,这是私有的,可能会导致应用被拒绝。

我想我会向 Apple 提出功能增强请求。

有没有人构建了一个非UIWebView-based PDF 查看器(带有源代码)?

【问题讨论】:

  • 如果这不起作用,您是否尝试将 PDF 放入 iframe(iPhone 文档不鼓励使用标准框架,但 iframe 可能没问题)并在父 HTML 文档中调用 JavaScript?
  • 我不认为可以从 Web 视图中获得页数。你的建议似乎没问题。尝试设置 scalesPagesToFit=YES 然后页面高度应该是浏览器视图/框架高度。
  • 我想当用户更改缩放级别时,您会感到沮丧!棘手。当 PDF 嵌入 iframe 时,您是否尝试过检查 DOM 模型——尽管这可能会开始转向非公共 API 使用?
  • 如果我在-webViewDidFinishLoad: 中记录 Web 视图的框架和边界,我得到的值不能反映内容的实际高度。 (例如,对于一个四页的 PDF,对于纵向显示的 PDF,我应该得到超过 456 像素的东西。)
  • 啊,是的,这是 Apple 添加的另一个令人着迷的东西。 JavaScript 中的坐标反映的坐标好像 iPhone 屏幕是桌面显示器尺寸而不是 iPhone 尺寸。我想他们这样做是为了最大限度地提高与桌面的兼容性。如果没有额外的概念混搭使其看起来像桌面的坐标系,我找不到在 JavaScript 中获取 iPhone 屏幕坐标的方法。我认为您需要与 Apple 的某个人成为朋友才能获得使用私有 API 或其他东西的许可。

标签: iphone pdf uiwebview cgpdfdocument


【解决方案1】:

所以这篇文章现在已经开放了很长一段时间,但由于它是谷歌搜索“scroll pdf uiwebview”的第一个条目,我想我会为未来的读者提供我的看法。

您确实可以使用纯 Java 脚本滚动到 PDF 文档中的特定页面。我已经在我们的博客 (http://apptech.next-munich.com/2011/02/pdf-in-uiwebview.html) 上发布了示例代码,但这里是您需要做的简短摘要:

  1. 使用 window.outerHeight DOM 属性查找呈现的 PDF 文档的总高度。
  2. 使用 window.innerHeight DOM 属性在浏览器坐标中查找浏览器窗口的高度。
  3. 使用 window.scrollTo(x, y) 函数跳转到页面。

不过,有一个问题是,您不能仅通过页数来设置 outerHeight 并跳转到您得到的内容。相反,您必须乘以 innerHeight/webView.bounds.size.height 比率。

【讨论】:

  • 作为我回答的后续:从 iOS 5 开始,这种技术不再适用。
  • 这也假设 pdf 由相同方向的页面组成。
【解决方案2】:

我认为您必须使用 PDF API 而不是 UIWebView 自己加载和显示 PDF。下面是一个关于如何模拟对齐滚动到矩形网格边界的可能想法,它可以帮助您为用户提供更像 UIWebView 的体验。

iPhone sdk Cocoa Touch - Pass touches down from parent UIView to child UIScrollview

【讨论】:

    【解决方案3】:

    我已经看到您的编辑有问题。 有没有人构建了一个非基于 UIWebView 的 PDF 查看器(带有源代码)?

    查看我的问题。

    Reading PDF files as string through iPhone application

    它具有在图像视图中显示每个 pdf 页面的功能。用户可以轻松更改页面。但缺失的地方如下。

    • 用户无法进行任何选择 - 因为它不是文本而是图像
    • 用户找不到任何文本。
    • 用户无法缩放(哦,是的 - 您可以将图像视图放在滚动视图中以实现缩放功能)

    【讨论】:

      【解决方案4】:

      通常用于加载 pdf 的 uiwebview 有它自己的滚动视图对象,您可以调用它。试试这样的:

          [webview.scrollView setContentOffset:CGPointMake(0, webview.scrollView.contentOffset.y + 100) animated:YES];    
      

      这会将 pdf 的视图向下滚动 100 像素。至于获取pdf的页码,我只能想象javascript是你需要看的。或者,如果您只知道 pdf 每页上的像素数,则根据需要增加或减少。 :)

      【讨论】:

        【解决方案5】:

        我遇到了类似的问题,我必须滚动到 PDF 中的特定页面(使用 UIWebView 显示),然后在 tableView(缩略图 tableview)中选择与该页面对应的单元格。

        所以我写了一段代码,可以让你滚动到 PDF 中的特定页面。

        我没有使用任何 javascript 代码。我只是跟踪每次应用于原始 PDF 页面的缩放比例并计算滚动到每个页面所需的更新偏移量。因此,即使 PDF 处于 zoomed 状态,它也可以工作。

        您可以找到代码here

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-23
          • 1970-01-01
          • 2018-11-17
          • 1970-01-01
          相关资源
          最近更新 更多