年后到现在,公司的项目紧,导致年初的计划并没有很好的执行。
最近熬夜越熬越晚,希望 6 月前能如期完成第一个目标。
今天谈谈直接在代码中加载 PDF 文件(公司的新需求,就地取材)。
我的需求背景:
1. 首先,随着移动端继续侵占 PC 的场景,手机上阅读越来越普遍,而一些既有的 PDF 文本也就被希望加载到手机端做友好展示
2. 其次,公司新项目的思路是展示型,尽可能减少网络交互(即尽可能少的调用接口获取数据),除了用户反馈、检测更新等,全项目只用了两个接口,大量业务逻辑是通过下载数据库在本地进行操作。因而,PDF 文件本地展示也顺应而出
移动端的差异
Android 端和 IOS 端的区别在于,
1. 优点:
Android 端 :提供了丰富的接口,足以进行良好的用户交互
IOS 端 : 调用简单,方法上大致有三种实现,最简单的就是用 UIwebView 直接展示
2. 缺点:
Android 端 : 调用麻烦,google 相关服务无法调用,逼迫 android 端采用第三方库加载(或者自己写。。。),同时,因为集成了第三方库的项目会变得相当庞大,打包后大小增加 15M 左右。
IOS 端 : 自定义麻烦,想要友好的交互需要手动修改,尤其是想要 PageController 的翻页效果,需要自己封装
下面进入代码主题
1. 先上 Android 端:
github 上 AndroidPdfViewer 的 star 较多,故选了这个
项目地址:
首先, 在 Gradle 中添加依赖
- compile 'com.github.barteksc:android-pdf-viewer:2.5.0'
其次, xml 布局文件
- <com.github.barteksc.pdfviewer.PDFView
- android:id="@+id/pdf_fragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
最后,代码调用:
- PDFView mPdfView = (PDFView) view.findViewById(R.id.pdf_fragment);
- mPdfView.fromAsset("sample.pdf")
- .defaultPage(0)//默认页
- .enableSwipe(true)//允许拖动
- .swipeHorizontal(false)//默认方向是竖轴的,改为true变为横轴
- .enableDoubletap(true)//允许双击放缩
- .onPageChange(this)//设置页码切换监听
- .load();
监听回调代码,(这里我用来记录用户上次浏览的页面)
- private int pdf_book_mark = 0;//定义默认的页码
- @Override
- public void onStop() {
- super.onStop();
- //stop 生命周期时 保存该页码到 SharePreference 中
- PreferenceUtil.save(getActivity(), "pdf_book_mark", pdf_book_mark);
- }
- @Override
- public void onPageChanged(int page, int pageCount) {
- LogUtil.i("page = " + page + " , pageCount =" + pageCount);
- pdf_book_mark = page;
- }
- //生命周期恢复展示时,默认加载页码 从SharePreference 中取出来
- private void lastBrowe() {
- ....
- mPdfView.defaultPage(PreferenceUtil.getSharePre(getActivity()).getInt("pdf_book_mark", 0))
- ...
- }
简单写了,看官可以自己尝试更多的 UI 交互
所有的调用接口如下:
- @Override
- public void onPageChanged(int page, int pageCount) {
- 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)
- .onDraw(onDrawListener) // allows to draw something on a provided canvas, above the current page
- .onLoad(onLoadCompleteListener) // called after document is loaded and starts to be rendered
- .onPageChange(onPageChangeListener)
- .onPageScroll(onPageScrollListener)
- .onError(onErrorListener)
- .onRender(onRenderListener) // called after document is rendered for the first time
- .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
- .load();
- }
onPageScroll/ onPageChange/ onRender / password / onDraw
这几个足以定制丰富的场景。详情见
2.IOS 端
我只实现了两种简单的方式,
第三种需要自定义,推荐参考
实现方式一 UIWebView:
- - (void)viewDidLoad {
- [super viewDidLoad];
- //获取sample.pdf 文件路径(本地)
- NSString *path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"pdf"];
- //UIWebView 的一般用法
- NSURL *url = [NSURL fileURLWithPath:path];
- NSURLRequest *request = [NSURLRequest requestWithURL:url];
- [self.webview loadRequest:request];
- }
这种方式只能浏览,safari 是不会让你有更多发挥空间的
实现方式二
首先 .h 文件中实现该协议
UIDocumentInteractionControllerDelegate
其次 .m 文件
- #import "PDFViewController.h"
- @interface PDFViewController ()
- @property (strong, nonatomic) UIDocumentInteractionController *documentInteractionController;
- - (IBAction)open:(id)sender;
- - (IBAction)preview:(id)sender;
- @end
- @implementation PDFViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- }
- - (IBAction)open:(id)sender {
- UIButton *button = (UIButton *)sender;
- NSURL *URL = [[NSBundle mainBundle] URLForResource:@"sample" withExtension:@"pdf"];
- if (URL) {
- // Initialize Document Interaction Controller
- self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:URL];
- // Configure Document Interaction Controller
- [self.documentInteractionController setDelegate:self];
- // Present Open In Menu
- [self.documentInteractionController presentOpenInMenuFromRect:[button frame] inView:self.view animated:YES];
- }
- }
- - (IBAction)preview:(id)sender {
- NSURL *URL = [[NSBundle mainBundle] URLForResource:@"sample" withExtension:@"pdf"];
- if (URL) {
- // Initialize Document Interaction Controller
- self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:URL];
- // Configure Document Interaction Controller
- [self.documentInteractionController setDelegate:self];
- // Preview PDF
- [self.documentInteractionController presentPreviewAnimated:YES];
- }
- }
- #pragma document
- -(UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller{
- return self;
- }
- @end
这种方式能在 View 上层再开启一层展示 PDF,同时带有一些 UI 交互可以操作。
大致如此。忙里偷闲,效果图晚上再贴。
明天愚人家,各位千万不要相信公司说加班的伎俩。
祝,四月愉快!
来源: http://www.bubuko.com/infodetail-2004246.html