android pdf框架-6,文本生成pdf

前文介绍如何使用图片生成pdf,这里介绍如何使用文本生成pdf

使用mupdf生成

mupdf生成的pdf略大,字体可以自定义.

生成的代码不复杂,也有好几种,以story的方式生成为例

fun createPdfFromText(sourcePath: String, destPath: String): Boolean {
        val text = EncodingDetect.readFile(sourcePath)
        val mediabox = Rect(0f, 0f, 500f, 707f) //A2
        val margin = 10f
        var writer = DocumentWriter(destPath, "PDF", "")

        var snark = "<!DOCTYPE html>" +
                "<style>" +
                "#body { font-family: \"Droid Sans\", sans-serif; }" +
                "</style>" +
                "<body>" +
                text +
                "</body></html>"
        val story = Story(snark, "", 12f)

        var more: Boolean

        do {
            val filled = Rect()
            val where = Rect(
                mediabox.x0 + margin,
                mediabox.y0 + margin,
                mediabox.x1 - margin,
                mediabox.y1 - margin
            )
            val dev: Device = writer.beginPage(mediabox)
            more = story.place(where, filled)
            story.draw(dev, Matrix.Identity())
            writer.endPage()
        } while (more)

        writer.close()
        writer.destroy()
        story.destroy()

        return true
    }

文档的读取,对于中文,可能会涉及到编码的处理.

先定义mediabox,就是纸张大小,这里是a2

然后用html生成story,最后写入就完成了

如果要自定义样式,颜色这些,api要去查如何使用.并不那么方便.

使用系统sdk生成

系统sdk是基于福昕的代码.但生成时可以使用view来设置样式,然后生成页面.样式比较容易控制,毕竟view长什么样是容易修改的.

读取文本是一样的.

val pdfDocument = PdfDocument()
        val pageWidth = PDF_PAGE_WIDTH.toInt()
        val pageHeight = PDF_PAGE_HEIGHT.toInt()
        val contentView =
            LayoutInflater.from(context).inflate(R.layout.pdf_content, parent, false) as TextView
        contentView.text = content
        val measureWidth = View.MeasureSpec.makeMeasureSpec(pageWidth, View.MeasureSpec.EXACTLY)
        val measuredHeight = View.MeasureSpec.makeMeasureSpec(pageHeight, View.MeasureSpec.EXACTLY)
        contentView.measure(measureWidth, measuredHeight)
        contentView.layout(0, 0, pageWidth, pageHeight)

建立文档对象,然后加载布局

val lineCount = contentView.lineCount
        var lineHeight = contentView.lineHeight
        if (contentView.lineSpacingMultiplier > 0) {
            lineHeight = (lineHeight * contentView.lineSpacingMultiplier).toInt()
        }
        val layout = contentView.layout
        var start = 0
        var end: Int
        var pageH = 0
        val paddingTopAndBottom: Int = Utils.dipToPixel(context, 40f)

设置边距40dp,读取行间距与行数.

因为设置了内容后,由textview自己就能计算出这些,然后根据这些信息,计算我们一页的高宽可以分成几页,然后每一页再用一个布局去生成就行了.

while (i < lineCount) {
            end = layout.getLineEnd(i)
            val line = content.substring(start, end) //指定行的内容
            start = end
            sb.append(line)
            pageH += lineHeight
            if (pageH >= pageHeight - paddingTopAndBottom) {
                Log.d(
                    "TextView",
                    String.format(
                        "============page line:%s,lh:%s,ph:%s==========",
                        i,
                        lineHeight,
                        pageHeight
                    )
                )
                createTxtPage(
                    context,
                    parent,
                    pdfDocument,
                    pageWidth,
                    pageHeight,
                    i + 1,
                    sb.toString()
                )
                pageH = 0
                sb.setLength(0)
            }
            i++
        }
        if (sb.length > 0) {
            Log.d("TextView", "last line ===")
            createTxtPage(context, parent, pdfDocument, pageWidth, pageHeight, i, sb.toString())
        }

这就是计算的过程,最后要再处理剩下的部分.

对于每一页的显示字符数处理完,接着就是对这些生成页面

private fun createTxtPage(
        context: Context?,
        parent: ViewGroup?,
        pdfDocument: PdfDocument,
        pageWidth: Int,
        pageHeight: Int,
        pageNo: Int,
        content: String?
    ) {
        val contentView =
            LayoutInflater.from(context).inflate(R.layout.pdf_content, parent, false) as TextView
        contentView.text = content
        val pageInfo: PdfDocument.PageInfo =
            PdfDocument.PageInfo.Builder(pageWidth, pageHeight, pageNo)
                .create()
        val page: PdfDocument.Page = pdfDocument.startPage(pageInfo)
        val pageCanvas: Canvas = page.getCanvas()
        val measureWidth = View.MeasureSpec.makeMeasureSpec(pageWidth, View.MeasureSpec.EXACTLY)
        val measuredHeight = View.MeasureSpec.makeMeasureSpec(pageHeight, View.MeasureSpec.EXACTLY)
        contentView.measure(measureWidth, measuredHeight)
        contentView.layout(0, 0, pageWidth, pageHeight)
        contentView.draw(pageCanvas)

        // finish the page
        pdfDocument.finishPage(page)
    }

页面同样用之前的布局,这样保持是一致的,否则高宽计算就不对了.这里因为不需要显示,所以我们要调用measure与layout再draw画出来 

保存就简单了

private fun savePdf(path: String?, document: PdfDocument): Boolean {
        val outputStream = FileOutputStream(path)
        try {
            document.writeTo(outputStream)
            return true
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            document.close()
        }
        return false
    }

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作 者: 李文琴,李翠霞 编 出版时间: 2014 丛编项: 普通高等学校计算机教育“十二五”规划教材 内容简介   本书作为Android课程的教材,系统全面地介绍了Android应用开发所涉及的各类知识。全书共分为21章,内容包括搭建Android开发环境,Android模拟器与工具,用户界面设计,Android常用组件,深入理解Activity,Intent和BroadcastReceiver广播,用户资源的使用,Android事件处理,通知、对话框与警告,Android程序调试,图像与动画处理技术,利用OpenGL实现3D图形,多媒体应用开发,Android数据存储技术,Content Provider实现数据共享,线程与消息处理,Service应用,网络通信技术,综合案例—家庭理财通,课程设计—猜猜鸡蛋放在哪只鞋子里,课程设计—简易涂鸦板。全书每章内容都与实例紧密结合,有助于学生理解知识,应用知识,达到学以致用的目的。本书附有配套DVD光盘,光盘中提供了本书所有实例、综合实例、实验、综合案例和课程设计的源代码,制作精良的电子课件PPT及教学录像,其中,源代码全部经过了精心测试,能够在Windows XP、Windows 2003、Windows 7、Windows 8系统下编译和运行。本书可作为应用型本科计算机专业、软件学院、高职软件专业及相关专业的教材,同时也可作为Android爱好者以及初、中级Android应用开发人员的参考工具书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值