How can i display a PDF file in an Android ImageView

10,592

Solution 1

There are three open source libraries, which combined, will do what you want. All are licensed with Apache V2 (or the Beer-Ware License)!

Note that V21 or above is required. But you can use an if-statement and an Intent as fallback, if required.

  1. Subsampling-scale-image-view: "A custom image view for Android, designed for photo galleries and displaying huge images"
  2. Subsampling-pdf-decoder: "A pdf decoder library for the subsampling scale image view"
  3. VerticalViewPager: This is optional, but i think you want to scroll up and down and not left and right.

The example how to implement this, is given in the sample of the decoder library.

1.) Gradle dependencies

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.) Implement a PagerAdapter, you can use this one

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.) Initiate and set the adapter for the VerticalViewPager

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

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

Solution 2

You can use webview for this and it is easy to implement. Do it like this

 @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);

    }
Share:
10,592
Stefan Lindner
Author by

Stefan Lindner

Softwaredeveloper in Augsburg/Germany.

Updated on June 18, 2022

Comments

  • Stefan Lindner
    Stefan Lindner almost 2 years

    Is it possible to display huge pdf files in an Android view?

    I just need to be able to display it, with pinch and zoom and other normal features that are implemented in ImageViews these days.