如何在Android ImageView中显示PDF文件

5

在Android视图中显示大型PDF文件是否可能?

我只需要能够显示它,并使用捏合缩放和其他这些天在ImageView中实现的正常功能。

2个回答

7
有三个开源库可以组合使用,以达到你想要的效果。所有这些库都是采用 Apache V2 (或 Beer-Ware 许可协议)授权的!
请注意,需要 V21 或更高版本。但如果需要,您可以使用 if 语句和 Intent 作为回退。
1. Subsampling-scale-image-view: "一个 Android 自定义图像视图,专门用于照片库和显示巨大图像" 2. Subsampling-pdf-decoder:"用于 subsampling 缩放图像视图的 pdf 解码器库" 3. VerticalViewPager: 这是可选的,但我认为你想上下滚动而不是左右滚动。
如何实现这一点的示例在解码器库的示例中给出。
1.) Gradle 依赖项
repositories {
  mavenCentral()
  jcenter()

  //decoder library, will soon be on jcenter 
  maven { url 'https://dl.bintray.com/n42/maven'} 
}

dependencies {
  compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.5.0'
  compile 'com.github.castorflex.verticalviewpager:library:19.0.1'
  compile 'de.number42:subsampling-pdf-decoder:0.1.0@aar'
}

2.) 实现一个 PagerAdapter,你可以使用这个

public class PDFPagerAdapter extends PagerAdapter {
  /**
   * context for the view
   */
  private Context context;

  /**
   * pdf file to show
   */
  private File file;

  /**
   * file descriptor of the PDF
   */
  private ParcelFileDescriptor mFileDescriptor;

  /**
   * this scale sets the size of the {@link PdfRenderer.Page} in the {@link
   * PDFRegionDecoder}.
   * Since it rescales the picture, it also sets the possible zoom level.
   */
  private float scale;

  /**
   * this renderer is only used to count the pages
   */
  private PdfRenderer renderer;

  /**
   * @param file the pdf file
   */
  public PDFPagerAdapter(Context context, File file) {
    super();
    this.context = context;
    this.file = file;
    this.scale = 8;
    try {
      mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
      renderer = new PdfRenderer(mFileDescriptor);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Instantiate an item. Therefor a {@link SubsamplingScaleImageView} with special decoders is
   * initialized and rendered.
   *
   * @param container isn't used here
   * @param position the current pdf page position
   */
  public Object instantiateItem(ViewGroup container, int position) {

    SubsamplingScaleImageView imageView = new SubsamplingScaleImageView(context);

    // the smaller this number, the smaller the chance to get an "outOfMemoryException"
    // still, values lower than 100 really do affect the quality of the pdf picture
    int minimumTileDpi = 120;
    imageView.setMinimumTileDpi(minimumTileDpi);

    //sets the PDFDecoder for the imageView
    imageView.setBitmapDecoderFactory(() -> new PDFDecoder(position, file, scale));

    //sets the PDFRegionDecoder for the imageView
    imageView.setRegionDecoderFactory(() -> new PDFRegionDecoder(position, file, scale));

    ImageSource source = ImageSource.uri(file.getAbsolutePath());

    imageView.setImage(source);

    container.addView(imageView);
    return imageView;
  }

  /**
   * gets the pdf site count
   *
   * @return pdf site count
   */
  public int getCount() {
    return renderer.getPageCount();
  }

  @Override public void destroyItem(ViewGroup container, int position, Object view) {
    container.removeView((View) view);
  }

  @Override public boolean isViewFromObject(View view, Object object) {
    return view == object;
  }
}

3.) 初始化并设置VerticalViewPager的适配器

VerticalViewPager pager = (VerticalViewPager) findViewById(R.id.pager);
File pdfFile = ....

PDFPagerAdapter pagerAdapter = new PDFPagerAdapter(this,pdfFile);
pager.setAdapter(pagerAdapter);

3
你可以使用WebView实现此功能,而且非常容易。可以这样做:
 @SuppressLint("NewApi")
    private void startWebView(String url) {

        // Create new webview Client to show progress dialog
        // When opening a url or click on link
        // Javascript inabled on webview
        web.getSettings().setJavaScriptEnabled(true);
        web.getSettings().setBuiltInZoomControls(true);
        web.getSettings().setDisplayZoomControls(false);
        web.getSettings().setLoadWithOverviewMode(true);
        web.getSettings().setUseWideViewPort(true);

        web.getSettings().setDomStorageEnabled(true);
        web.setWebChromeClient(new WebChromeClient());
//        web.getSettings().setPluginState(WebSettings.PluginState.ON);
        web.setWebViewClient(new WebViewClient() {
            ProgressDialog progressDialog;

            // If you will not use this method url links are opeen in new brower
            // not in webview
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
            @SuppressWarnings("deprecation")
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, final String failingUrl) {
                web.loadUrl("about:blank");


            }

            // Show loader on url load
            public void onLoadResource(WebView view, String url) {
               /* if (progressDialog == null) {
                    // in standard case YourActivity.this
                    if (getActivity() != null) {
                        progressDialog = new ProgressDialog(getActivity());
                        progressDialog.setMessage("Loading...");
                        progressDialog.show();
                    }

                }*/

            }

            public void onPageFinished(WebView view, String url) {
                try {
                    setProgressBar(false);
                } catch (Exception e) {

                }
            }

        });


        // Load url in webview
        web.loadUrl(url);

    }

你好Rahul,感谢你的回答。你是对的,使用WebView是一种可能性。我只是想展示一种其他/新的方法来在Android应用程序中显示PDF文件。 - Stefan Lindner
根据SO上的这篇文章https://dev59.com/MHE95IYBdhLWcg3wGqEH,API Level 21(棒棒糖)引入了一个新的PdfRenderer类。@StefanLindner - Rahul Khurana
是的,你说得对,我甚至在我的PDFPagerAdapter类(以及库的解码器类)中使用它。问题是,没有缩放或任何实现。上面的解决方案甚至对pdf图像进行了子采样,因此您不会遇到任何内存问题。 - Stefan Lindner
好的,那么你可以使用WebView或者使用一些库。如果我的回答在某种程度上对您有所帮助,我能否得到一个赞,以便对其他人有所帮助。 - Rahul Khurana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接