本人Android萌新, 因为最近需求.需要将PDF文件渲染到Android应用中进行展示.,于是马上去寻找解析PDF的库;第一条展示的就是 : Android PdfViewer:
github地址:
https://github.com/barteksc/AndroidPdfViewer
打开官网看见这一坨代码:
pdfView.fromUri(Uri)
or
pdfView.fromFile(File)
or
pdfView.fromBytes(byte[])
or
pdfView.fromStream(InputStream) // stream is written to bytearray - native code cannot use Java Streams
or
pdfView.fromSource(DocumentSource)
or
pdfView.fromAsset(String)
.pages(0, 2, 1, 3, 3, 3) // all pages are displayed by default
.enableSwipe(true) // allows to block changing pages using swipe
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
// allows to draw something on the current page, usually visible in the middle of the screen
.onDraw(onDrawListener)
// allows to draw something on all pages, separately for every page. Called only for visible pages
.onDrawAll(onDrawListener)
.onLoad(onLoadCompleteListener) // called after document is loaded and starts to be rendered
.onPageChange(onPageChangeListener)
.onPageScroll(onPageScrollListener)
.onError(onErrorListener)
.onPageError(onPageErrorListener)
.onRender(onRenderListener) // called after document is rendered for the first time
// called on single tap, return true if handled, false to toggle scroll handle visibility
.onTap(onTapListener)
.onLongPress(onLongPressListener)
.enableAnnotationRendering(false) // render annotations (such as comments, colors or forms)
.password(null)
.scrollHandle(null)
.enableAntialiasing(true) // improve rendering a little bit on low-res screens
// spacing between pages in dp. To define spacing color, set view background
.spacing(0)
.autoSpacing(false) // add dynamic spacing to fit each page on its own on the screen
.linkHandler(DefaultLinkHandler)
.pageFitPolicy(FitPolicy.WIDTH) // mode to fit pages in the view
.fitEachPage(false) // fit each page to the view, else smaller pages are scaled relative to largest page.
.pageSnap(false) // snap pages to screen boundaries
.pageFling(false) // make a fling change only a single page like ViewPager
.nightMode(false) // toggle night mode
.load();
我就知道我找对了[手动滑稽];从上面的代码可以看出来,我们获取这个组件,通过代码链的形式来配置一系列参数,最后通过load()加载就可以了,真的十分的amaze呀!!!
那么废话不多说我们的直接根据他的文档介绍来完成我们的需求:
需求:添加,渲染PDF文件,并且能够像ViewPage一样滑动;
总共分为三步:
那么第一步:既然要用我们的外部库,那么就需要引入我们的依赖:
implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'
implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'
这里有的两个版本,第一个3.2.0-beta.1是目前最新的版本,我们导入这个依赖就可以了,下面的2.8.2的版本,那么是目前比较稳定的版本,但是功能似乎没有3.2.0-beta全面,所以我不考虑使用;并且为了我们开发方便这里我开启了 ViewBinding;
viewBinding {
enabled = true
}
implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'
项目同步成功之后我们还需要添加两个权限:用于读写文件
当然如果我们Android版本高于6.0,那么还需要动态申请权限,这一步我们拿到第二步来完成;如果以上步骤都已经完成了,那么恭喜你可以引入我们的PDF文件了:
引入文件非常简单,我们只需要在项目的main目录下创建一个assets目录,并且将我们需要PDF文件复制进去即可,就像这样:
文件导入成功我们开始写页面布局:
按钮背景:
这里我们采用帧布局的形式,页面也很简单,我解释一下,我们先加上PDFView(这个就是放置PDF的容器)然后宽高占满父布局,然后放置一个按钮在这个容器的上面,这个按钮固定在右下角;简单的布局就完成了;
那么开始第二步:第二步事件我们的PDF文件读取到Android并且渲染到屏幕上,那么Android PdfViewer为我们提供了以下几种读取文件的方法:
pdfView.fromUri(Uri)
pdfView.fromFile(File)
pdfView.fromBytes(byte[])
pdfView.fromStream(InputStream)
pdfView.fromAsset(String)
我们发现它能够通过URL , 文件 , 流等形式来读取PDF文件之外,它居然提供了fromAsset()这个方法,没错就是你想的那样,这个方法能够直接读取我们Asset目录下的文件;我们直接传入文件名字即可;这样我们读取PDF文件就非常简单了;
//先声明变量
private ActivityMainBinding mActivityMainBinding;
private static final int REQUEST_EXTERNAL_STORAGE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(mActivityMainBinding.getRoot());
getPermission();
mActivityMainBinding.showPdf.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mActivityMainBinding.pdfView.fromAsset("data.pdf").load();
}
/**
* 权限列表的
*/
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
/**
* 获取动态权限
*/
public void getPermission() {
int hasWriteContactsPermission = ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
Log.d("yx", "get permission");
ActivityCompat.requestPermissions(MainActivity.this,
PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
Log.d("yx", "get permission2");
ActivityCompat.requestPermissions(MainActivity.this,
PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
Log.d("yx", "wait for PERMISSION_GRANTED");
while ((ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)) != PackageManager.PERMISSION_GRANTED) {
}
Log.d("yx", "wait for PERMISSION_GRANTED finish");
}
@Override
protected void onResume() {
/**
* 设置为横屏
*/
if(getRequestedOrientation()!= ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
super.onResume();
}
这里有点长,但总体完成的工作不多,首先我们初始化了ViewBindiing对象,并且调用了getPermission这个的方法,这个方法就是我前面说的动态的申请权限了,传入一个权限列表,系统会向用户申请权限列表中的权限,直接拿来复制使用即可(我也是复制的doge);下面重写onResume()方法,目的是为了屏幕能够强制横向;
重头戏在下面,我们为按钮设置了一个点击监听,在回调接口中我们写入加载PDF文件的代码,看起来是非常的简单,但是此时我们运行程序,然后点击按钮就能够成功加载PDF了;但是看起来展示的效果不尽人意;
那么光速进入我们的第三步:接下来我们调整PDF展示的格式,还记得上面那一坨代码吗?里面展示了各种配置方法,我们传入参数就可展示效果 . 那么还记得我们需求吗?PDF要像ViewPage那样展示;并且能够适应屏幕:
首先我们屏幕需要滑动:
enableSwipe(true) //控制屏幕滑动,默认为true能够滑动
为了防止用户双击方法,我们需要禁用双击:
enableDoubletap(false) //禁用双击,默认为true,可以双击
想让页面能够像ViewPage一样滑动(官方文档也有介绍):
swipeHorizontal(true) //开启横向滑动 因为我们强制横屏 pageSnap(true) //启动页面捕捉 autoSpacing(true) //自动间距 pageFling(true) //开启翻页
最后我们想要PDF文档能够适应屏幕大小:
pageFitPolicy(FitPolicy.WIDTH) //控制PDF文件适配模式 有以下三种模式
这里我就直接翻译过来的,怕解释错误,我的理解就是一个以高为主,一个以宽为主,一个则自适应;那么了解完所有配置方法之后我们来改进代码:
mActivityMainBinding.pdfView.fromAsset("data.pdf")
//启用滑动
.enableSwipe(true)
//禁用双击
.enableDoubletap(false)
.swipeHorizontal(true)
.pageSnap(true)
.autoSpacing(true)
.pageFling(true)
.pageFitPolicy(FitPolicy.BOTH)
.load();
我们按照上面的方法进行配置,适配我选择的BOTH模式,最后别忘记了.load()进行加载;那么整个项目我们就完成了;对我来说还是一次非常不错的体验;毕竟又学到了很多东西;(尤其是看文档这一块的);当然PDFviewer还有很多配置的方法我没有见到,大家可以去github官网去逐一 的体验,这里就不过多的赘述了;
最终的效果:
第一次写博客,不足的地方请多多包含,有错误的地方请在评论区指正,本人Android开发入门,还需多多学习,希望大佬们不要嫌弃;
这里也提前祝大家新春快乐,感谢!