-
前言
最近项目上有一个需求,需要在Android端加载显示pdf文档,因为没有相关的经验,在刚接到需求的时候,第一想法就是打开程序员的第二大脑进行搜索,搜索结果还是蛮理想的,了解到了MuPDF,它支持多种文档格式,例如 PDF、XPS、OpenXPS、CBZ、EPUB 和 FictionBook 2。
我这里要记录的是 android-pdfview。PDFView是这个库中最核心的类,用于加载pdf文件,PDFView是的实现是继承于SurfaceView来实现的。主要用到了建造者模式来设置相关的属性。
另外还可以通过浏览器进行加载pdf等等。
-
效果图
-
引用
android-pdfview的依赖为:
compile 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'
-
权限
这里需要添加网络权限,将服务器上的pdf文档下载到本地保存。
<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
另外还需要添加文件读写的权限。
<!-- 写入外部存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 读取外部存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
本文编辑时,对应的demo是在我们公司定制的开发板上边运行的,所有权限只需在manifest里边添加,无需手动申请权限,这里需要注意,自己进行文件读写权限的申请。
-
布局文件
布局文件就非常简单了,直接在activity对应的布局中,添加一个PDFView控件,宽高均设置为match_parent就可以了。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.load.pdfview.LoadPdfViewActivity">
<com.joanzapata.pdfview.PDFView
android:id="@+id/loadPdfView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
-
文档下载
看到上边这个图片,顾名思义要开始撸代码了!!!
-
View层
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_load_pdf_view) //找控件 loadPdfView = findViewById(R.id.loadPdfView) onLoadingView = findViewById(R.id.onLoadingView) //下载文档的Presenter mLoadFilePresenter = LoadFilePresenter() //绑定页面 mLoadFilePresenter?.attachView(this) //下载文档 mLoadFilePresenter?.downLoadFile("要加载的文档对应的服务器链接地址。") }
在页面onCreate完成之后,将服务器上的pdf文档进行下载至本地。
-
Presenter层
override fun downLoadFile(fileUrl: String) { //提示正在加载文档 view?.downLoadingFile() //创建下载完成的回调 val mLoadFileModel: DloadFileInterface.LoadFileModelInterface = LoadFileModel() //开始下载pdf文档 mLoadFileModel.downLoadFile(object : DownLoadFileListener { //是否下载成功的监听 override fun onDownLoadListen(isSuccessFlag: Boolean, filePath: String) { if (isAvailable()!!)//判断view是都可见 view?.downLoadFileComplete(isSuccessFlag, filePath)//告诉view层,文档已经下载完了 } }, fileUrl) }
-
Model层
//开始下载文档 override fun downLoadFile(mDownLoadFileListener: DloadFileInterface.DownLoadFileListener, fileUrl: String) { val mDownLoadFileUtils = DownLoadFileUtils( "training_plan.pdf",//下载文档完成后本地存储文档的名称 fileUrl,//服务器上文档的url object : DownLoadFileUtils.DownLoadCompleteListener {//下载完成的回调 override fun onDownLoadCompleteListener(isSuccessFlag: Boolean, filePath: String?) { if (filePath != null)//判空处理 mDownLoadFileListener.onDownLoadListen(isSuccessFlag, filePath) } } ) //这里要在子线程进行文档的下载 val scheduledExecutorService = Executors.newSingleThreadScheduledExecutor() scheduledExecutorService.execute(mDownLoadFileUtils) }
因为下载文档这地方,既有文件存储又有网络加载的过程,为了避免ANR,所有要在子线程中进行。
-
加载文档
fun loadPdfFile2Show(filePath: String) {
//判断当前页面是否已经销毁
if (!isAvailable())
return
val file = File(filePath)
if (!file.exists() || !file.isFile) {
toastMessage("文件不存在或文件已损坏!")
return
}
loadPdfView?.fromFile(file)
?.defaultPage(1)//默认加载文档的第defaultPage页 默认设置为第一页
?.showMinimap(false)//pdf放大的时候,是否在右上角生成引导图 默认设置为不生成
?.enableSwipe(true)//是否允许翻页,默认为允许翻页
?.onDraw(object : OnDrawListener {
//正在绘制图像的监听
override fun onLayerDrawn(canvas: Canvas?, pageWidth: Float, pageHeight: Float, displayedPage: Int) {
LogUtils.d(TAG, "onLayerDrawn====")
}
})
?.onLoad(object : OnLoadCompleteListener {
//加载完成的监听
override fun loadComplete(nbPages: Int) {
LogUtils.d(TAG, "loadComplete====")
}
})
?.onPageChange(object : OnPageChangeListener {
//翻页的监听
override fun onPageChanged(page: Int, pageCount: Int) {
LogUtils.d(TAG, "onPageChanged===")
}
})
?.load()
}
在加载对应的pdf文档之前一定要进行判断,文档是否存在,否则你要加载的文档不存在的话,应用会直接crash掉。
if (!file.exists() || !file.isFile) {
toastMessage("文件不存在或文件已损坏!")
return
}
-
总结
android-pdfview使用起来还是比较简单的,而且功能比较强大,如果有兴趣或者有更高层次的需求可以研究一下,本人现在只局限于加载并显示文档这里,后边会进行深层次的学习后进行相关分享。
-
结束
最后附上demo下载地址!