行业知识
android pdf框架-6,文本生成pdf
2026-11-15 04:53:43
来源:互联网转载
前���介绍如何使用图片生成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 = "" + "" + "#body { font-family: \"Droid Sans\", sans-serif; }" + "" + "" + text + "" 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 = 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 }
上一篇:网易服务器满人怎么卡进去?