赞
踩
前文介绍如何使用图片生成pdf,这里介绍如何使用文本生成pdf
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是基于福昕的代码.但生成时可以使用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
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。