有时候项目中可能会遇到这样的需求,如何将android中界面显示的内容生成pdf,这里讲述的是使用android原生的PdfDocument,并没有使用框架,其一是使用起来非常的简单,但是也会也到一些坑,下面将一一道来。

首先,先来说下这个类的使用,使用非常的简单,直接参考官方文档或是在源码中都能查看到简单的实例,这里就先看下源码中介绍的简单使用:

 * // create a new document * PdfDocument document = new PdfDocument(); * * // crate a page description * PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1).create(); * * // start a page * Page page = document.startPage(pageInfo); * * // draw something on the page * View content = getContentView(); * content.draw(page.getCanvas()); * * // finish the page * document.finishPage(page); * . . . * // add more pages * . . . * // write the document content * document.writeTo(getOutputStream()); * * // close the document * document.close();

这是android源码中的介绍(API 27),但是在构建PageInfo的时候却没有上面Builder()这样的构造方法,而是:

PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(pageWidth,pageHeight,pageNumber).create();

这里说下Builder()中这几个参数的作用:

        pageWidth:pdf页面的宽度(文档介绍:The page width in PostScript );

        pageHeight:pdf页面的高度(文档介绍:The page height in PostScript );

        pageNumber:pdf页面的页数,在实际使用过程,发现这个参数并没起到什么作用;

说到这,再来看下我在实际应用中的使用:

    private void pdfModel(){        PdfDocument document = new PdfDocument();        // ll_model是一个LinearLayout        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(ll_model.getWidth(),ll_model.getHeight(),1).create();        PdfDocument.Page page = document.startPage(pageInfo);        ll_model.draw(page.getCanvas());        document.finishPage(page);        File file = new File(getPdfFilePath(pdfName));        FileOutputStream outputStream = new FileOutputStream(file);        try {            document.writeTo(outputStream);        } catch (IOException e) {            e.printStackTrace();        }        document.close();    }

这里就是将一个LinearLayout中的内容生成了pdf,如果LinearLayout中内容很长,可以使用ScrollView在包裹一下。这里生成的pdf只是一页,当文字内容在三百行以内时(根据自己生成的内容而定),生成的pdf显示是没什么问题的,但是内容在多一些时,你就会发现,pdf依旧可以生成,但是查看的时候,pdf中的内容却显示不出来了。

遇到这问题的时候,当时就在想是不是生成一页的pdf高度太高了导致的,所以这时就在想是不是可以分页,但当时我的一个TextView显示的内容可能就有上千行,所以还涉及对这一个view的内容生成的pdf进行分页,结合代码发现,将view中的内容生成pdf文件,实际是会将view中的内容先绘制在PageInfo中的一块画布上(canvas),所以就想着可不可以对这块画布做些处理,跟着这个思路走,就有了对TextView中内容进行分页的做法:

    private void pdfInterviewContent(PdfDocument document){        // 一页pdf的高度        int onePageHeight = tv_content.getLineHeight()*30;        // TextView中总共有多少行        int lineCount = tv_content.getLineCount();        // 计算这个TextView需要分成多少页        int pdfCount = lineCount % 30 == 0 ? lineCount/30 : lineCount/30+1;        for (int i = 0; i < pdfCount; i++) {            PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(tv_content.getWidth(),onePageHeight+120,1)                    .setContentRect(new Rect(0,60,tv_content.getWidth(),onePageHeight+60))                    .create();            PdfDocument.Page page = document.startPage(pageInfo);            Canvas canvas = page.getCanvas();            canvas.translate(0,-onePageHeight*i);            tv_content.draw(canvas);            document.finishPage(page);        }        File file = new File(getPdfFilePath(pdfName));        FileOutputStream outputStream = new FileOutputStream(file);        try {            document.writeTo(outputStream);        } catch (IOException e) {            e.printStackTrace();        }        document.close();    }

这里在说下构建PageInfo中多的setContentRect()这个方法,这个方法去掉也是不影响生产pdf的,这个方法影响的是生成pdf的显示效果,比如这里的60就是说每一页生成的pdf距离这一页的顶部和底部各是60,如果这里把这个方法去电,那么生成的pdf内容将是顶着页面的顶部和底部的。在构建完PageInfo后,就可以拿到画布(canvas)了,为了生成对应位置的内容,这里就需要对画布进行一个平移操作了,这个平移操作就看你是怎么去划分了,这里是将一个页面的高度作为基本的平移单位。

至此,生成pdf以及分页就全都ok了,不过这里还有一个问题没怎么弄明白,就是生成一页文字的pdf的大小差不多是7M多,但我生成30页文字的pdf也就多了1M左右,目前还不明白这其中原因。

对于PdfDocument的学习,建议多看看源码及注释,代码量不大,加注释也就四百来行。

 

更多相关文章

  1. 《Android Studio开发实战 从零基础到App上线(第2版)》资源下载
  2. Android垃圾回收实质内容解析
  3. android中使用httpclient方法获得网页内容并对json对象解析
  4. Android WebView加载https页面不能正常显示资源问题
  5. 移动开发 - Android - 实现两个页面(Activity)的简单跳转(Intent
  6. Android跳转页面的基本方式
  7. android 页面停几秒后跳转
  8. Android 监听短信内容变化,并发送到自己的手机

随机推荐

  1. Android RoboGuice 使用指南(19):发送接
  2. Android ProgressDialog错误:Unable to a
  3. Android Jetpack学习之Lifecycle
  4. Android 开发常用的工具类
  5. Android 常见权限列表
  6. Android ToolBar Menu按钮的动态隐藏
  7. 一插上USB外设以后直接跳到相应的…
  8. Android 为什么 dp2px 或 px2dp 公式需要
  9. 11Android/Sdk/ndk-bundle/toolchains/mi
  10. Android杀死进程方法