How do I display a PDF file in Android ImageView… here is a solution to the problem.
How do I display a PDF file in Android ImageView
Is it possible to display huge pdf files in Android View?
I just need to be able to display it, using zoom and zoom and other normal features implemented in ImageViews these days.
Solution
There are three open-source libraries, combine them to meet your needs. All of them are licensed under Apache V2 (or Beer-Ware licenses)!
Note that V21 or later is required. However, if needed, you can use an if statement and an intent as a fallback.
- Subsampling-scale-image-view:”Android’s custom ImageView, Designed for photo galleries and displaying large images”
- Subsampling-pdf-decoder: “pdf decoder library for subsampling scale ImageView”
- VerticalViewPager: This is optional, but I think you want to scroll up and down instead of left and right.
An
example of how to implement it is given in the example 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:[email protected]'
}
2.) Implement a PagerAdapter, you can use this
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.) Start and set up the adapter for VerticalViewPager
VerticalViewPager pager = (VerticalViewPager) findViewById(R.id.pager);
File pdfFile = ....
PDFPagerAdapter pagerAdapter = new PDFPagerAdapter(this,pdfFile);
pager.setAdapter(pagerAdapter);