使用PdfDocument导出长文本PDF的分页问题求助
Android PDF导出:长富文本分页解决方案
针对你遇到的长富文本溢出页面、无法分页的问题,直接给你可行的实现方案:
1. 判断文本是否超出页面可用空间
首先明确页面剩余可用高度:即当前页面中,从当前绘制起始Y坐标(mYPosOnPage)到页面底部边距的距离。假设你定义了cTopMargin(上边距)、cBottomMargin(下边距)、mPageHeight(页面总高度),计算方式如下:
val remainingPageHeight = mPageHeight - cBottomMargin - mYPosOnPage
然后通过StaticLayout的height属性获取整个文本需要的总高度,和剩余高度对比即可判断是否溢出:
val spanText = Html.fromHtml(longHtmlText, Html.FROM_HTML_MODE_COMPACT) val fullLayout = StaticLayout.Builder .obtain(spanText, 0, spanText.length, textPaint, mPageWidth - 2 * cLeftRightMargin) .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setLineSpacing(0f, 1.0f) .build() // 文本总高度超过页面剩余可用高度,即为溢出 val isOverflow = fullLayout.height > remainingPageHeight
2. 截断文本并分页绘制
如果文本溢出,需要精准找到截断位置,分页面绘制剩余内容:
步骤1:找到当前页可容纳的最后一行
利用StaticLayout.getLineForVertical()方法,传入剩余可用高度,得到当前页能显示的最后一行索引:
val lastVisibleLine = fullLayout.getLineForVertical(remainingPageHeight)
步骤2:获取文本截断索引
通过getLineEnd()获取该行对应的文本结束位置,注意要判断是否是文本的最后一行(避免无意义截断):
val endIndex = fullLayout.getLineEnd(lastVisibleLine) val isTextFullyDisplayed = lastVisibleLine == fullLayout.lineCount - 1
步骤3:绘制当前页内容
创建仅包含当前页内容的StaticLayout,绘制到当前页面:
val currentPageText = spanText.subSequence(0, endIndex) val currentLayout = StaticLayout.Builder .obtain(currentPageText, 0, currentPageText.length, textPaint, mPageWidth - 2 * cLeftRightMargin) .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setLineSpacing(0f, 1.0f) .build() canvas.save() canvas.translate(cLeftRightMargin.toFloat(), mYPosOnPage.toFloat()) currentLayout.draw(canvas) canvas.restore()
步骤4:处理剩余文本到下一页
如果还有剩余文本,创建新的PDF页面,重复上述流程:
if (!isTextFullyDisplayed) { // 剩余未绘制的文本 val remainingText = spanText.subSequence(endIndex, spanText.length) // 新建PDF页面 val nextPageInfo = PdfDocument.PageInfo.Builder(mPageWidth, mPageHeight, currentPageNum + 1).create() val nextPage = pdfDocument.startPage(nextPageInfo) val nextCanvas = nextPage.canvas // 新页面从顶部边距开始绘制 val nextYPos = cTopMargin // 复用绘制逻辑处理剩余文本 val remainingLayout = StaticLayout.Builder .obtain(remainingText, 0, remainingText.length, textPaint, mPageWidth - 2 * cLeftRightMargin) .setAlignment(Layout.Alignment.ALIGN_NORMAL) .setLineSpacing(0f, 1.0f) .build() nextCanvas.save() nextCanvas.translate(cLeftRightMargin.toFloat(), nextYPos.toFloat()) remainingLayout.draw(nextCanvas) nextCanvas.restore() pdfDocument.finishPage(nextPage) }
关于TextPaint初始化的说明
TextPaint的初始化是必要的,StaticLayout完全依赖它计算文本的尺寸、样式(字体大小、颜色、字重等),如果省略,会使用系统默认值,导致绘制效果不符合预期,建议保留当前的初始化代码。
内容的提问来源于stack exchange,提问作者Michel
相关产品推荐
相关产品推荐

