前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android项目实战(六十一):pdf文件用图片方式预览

Android项目实战(六十一):pdf文件用图片方式预览

作者头像
听着music睡
发布2020-12-21 11:29:23
8220
发布2020-12-21 11:29:23
举报
文章被收录于专栏:Android干货Android干货

前言:

Android不支持pdf的在线预览,网上有多种预览pdf的实现方式,点此查看总结

这里实现一种先下载pdf文件到本地,再将文件转成图片显示的的操作

一个工具类:

代码语言:javascript
复制
import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.graphics.Bitmap;
import android.graphics.pdf.PdfRenderer;
import android.os.ParcelFileDescriptor;
import android.support.annotation.WorkerThread;
import android.util.Log;
import android.widget.ImageView;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import info.ecloud.core.util.ToastUtils;
import info.ecloud.merchant.app.BaseObserve;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

public class PdfRendererBasicViewModel extends AndroidViewModel {
    private static final String TAG = "PdfRendererBasic";

    /**
     * The filename of the PDF.
     */
    private static final String FILENAME = "sample.pdf";

    private final MutableLiveData<PageInfo> mPageInfo = new MutableLiveData<>();
    private final MutableLiveData<Bitmap> mPageBitmap = new MutableLiveData<>();
    private final MutableLiveData<Boolean> mPreviousEnabled = new MutableLiveData<>();
    private final MutableLiveData<Boolean> mNextEnabled = new MutableLiveData<>();

    private final Executor mExecutor;
    private ParcelFileDescriptor mFileDescriptor;
    private PdfRenderer mPdfRenderer;
    private PdfRenderer.Page mCurrentPage;
    private boolean mCleared;
    public File pdfFile ;
    public ImageView pdfView ;


    @SuppressWarnings("unused")
    public PdfRendererBasicViewModel(Application application , File pdfFile , ImageView pdfView) {
        this(application, false);
        this.pdfFile = pdfFile;
        this.pdfView = pdfView;
    }

    PdfRendererBasicViewModel(Application application, boolean useInstantExecutor) {
        super(application);
        if (useInstantExecutor) {
            mExecutor = Runnable::run;
        } else {
            mExecutor = Executors.newSingleThreadExecutor();
        }
        mExecutor.execute(() -> {
            try {
                openPdfRenderer();
                showPage(0);
                if (mCleared) {
                    closePdfRenderer();
                }
            } catch (IOException e) {
                Log.e(TAG, "Failed to open PdfRenderer", e);
            }
        });
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        mExecutor.execute(() -> {
            try {
                closePdfRenderer();
                mCleared = true;
            } catch (IOException e) {
                Log.i(TAG, "Failed to close PdfRenderer", e);
            }
        });
    }

    public LiveData<PageInfo> getPageInfo() {
        return mPageInfo;
    }

    public LiveData<Bitmap> getPageBitmap() {
        Log.i("xqxinfo","bitmap==>"+(mPageBitmap==null));
        return mPageBitmap;
    }

    public LiveData<Boolean> getPreviousEnabled() {
        return mPreviousEnabled;
    }

    public LiveData<Boolean> getNextEnabled() {
        return mNextEnabled;
    }

    void showPrevious() {
        if (mPdfRenderer == null || mCurrentPage == null) {
            return;
        }
        final int index = mCurrentPage.getIndex();
        if (index > 0) {
            mExecutor.execute(() -> showPage(index - 1));
        }
    }

    public void showNext() {
        if (mPdfRenderer == null || mCurrentPage == null) {
            return;
        }
        final int index = mCurrentPage.getIndex();
        if (index + 1 < mPdfRenderer.getPageCount()) {
            mExecutor.execute(() -> showPage(index + 1));
        }
    }
    public void showLast() {
        if (mPdfRenderer == null || mCurrentPage == null) {
            return;
        }
        final int index = mCurrentPage.getIndex();
        if (index - 1 >=0) {
            mExecutor.execute(() -> showPage(index - 1));
        }
    }

    @WorkerThread
    private void openPdfRenderer() throws IOException {
        final File file = pdfFile;
        if (!file.exists()) {
            ToastUtils.showLong("文件预览失败");
            return;
        }
        Log.i("xqxinfo","file->"+file.getAbsolutePath());
        mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
        if (mFileDescriptor != null) {
            mPdfRenderer = new PdfRenderer(mFileDescriptor);
        }
    }

    @WorkerThread
    private void closePdfRenderer() throws IOException {
        if (mCurrentPage != null) {
            mCurrentPage.close();
        }
        if (mPdfRenderer != null) {
            mPdfRenderer.close();
        }
        if (mFileDescriptor != null) {
            mFileDescriptor.close();
        }
    }

    @WorkerThread
    private void showPage(int index) {
        // Make sure to close the current page before opening another one.
        if (null != mCurrentPage) {
            mCurrentPage.close();
        }
        // Use `openPage` to open a specific page in PDF.
        mCurrentPage = mPdfRenderer.openPage(index);
        Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
                Bitmap.Config.ARGB_8888);
        // Here, we render the page onto the Bitmap.
        // To render a portion of the page, use the second and third parameter. Pass nulls to get
        // the default result.
        // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
        mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
        mPageBitmap.postValue(bitmap);
        Observable.timer(10, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new BaseObserve<Long>() {
                    @Override
                    public void onNext(Long aLong) {
                        pdfView.setImageBitmap(bitmap);
                    }
                });
        final int count = mPdfRenderer.getPageCount();
        mPageInfo.postValue(new PageInfo(index, count));
        mPreviousEnabled.postValue(index > 0);
        mNextEnabled.postValue(index + 1 < count);
    }

    static class PageInfo {
        final int index;
        final int count;

        PageInfo(int index, int count) {
            this.index = index;
            this.count = count;
        }
    }
}

使用方法:

代码语言:javascript
复制
public PdfRendererBasicViewModel(Application application , File pdfFile , ImageView pdfView) 

注意,因为是图片方式显示,依赖于一个ImageView , 每次只显示pdf一页的数据预览,额外提供上一页、下一页的方法使用

这里只提供基本使用,可以自行拓展功能,不限于图片缩放,多页展示等

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-12-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档