在我的应用程序中,我可以选择将文本导出为 PDF。为了实现这一目标,我利用了
PdfDocument
类,一切都很好。最近,我什至更新了它来处理跨文本,而且这也可以无缝工作。
但是,当文本长度超过页面大小(减去顶部和底部边距)时,就会出现问题。文字只是继续,在底部,你甚至可以看到半行(该行的上半部分)。
下面是我的代码中负责编写(可能)长文本的部分。为了便于阅读,我省略了创建类实例、设置页面大小等部分。
textPaint.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)
textPaint.textSize = cNormalSize
textPaint.color = ContextCompat.getColor(mContext, R.color.black)
textPaint.isUnderlineText = false
val spanText = Html.fromHtml(longHtmlText, Html.FROM_HTML_MODE_COMPACT)
val staticLayout = StaticLayout.Builder
.obtain(spanText, 0 , spanText.length, textPaint, mPageWidth - (2 * cLeftRightMargin))
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.setLineSpacing(0f, 1.0f)
.build()
canvas.save()
canvas.translate(cLeftRightMargin.toFloat(), mYPosOnPage.toFloat())
staticLayout.draw(canvas)
canvas.restore()
我不确定
textPaint
的初始化是否有必要(正在进行中)。
但是,问题是:
如何确定文本(spanText)是否比可用大小长?
如何截断该点的文本并将剩余部分打印在下一页上?
我一直在寻找一种在某处设置高度的方法,但到目前为止还没有运气。
经过大量尝试和转储我的应用程序,我设法找到了解决方案。
当然你可以使用一些库,但我不想要这个,因为学习它是如何工作的更有趣。所以对于所有有相同心态的人来说,我是如何解决这个问题的。
我有第一种方法,我在页面上写一个标题,然后从长文本开始。因此,在我的第一个方法中,我首先编写标题,然后调用第二个方法,该方法将作为递归调用处理长文本。
调用第二个方法很简单:
val spanText = Html.fromHtml(longHtmlText!!, Html.FROM_HTML_MODE_COMPACT)
page = printLongText(pageInfo, spanText, page, 1, mYPosOnPage)
mYPosOnPage 是偏移量。在第一页上,它包含到我的标题下方的偏移量。在下面的方法中,我将其覆盖为 1 之后所有页面的页边距。
然后递归方法不断地用长文本的剩余部分调用自身,直到什么都没有剩下。
private fun printLongText(pageInfo: PdfDocument.PageInfo,
spanText: Spanned,
page: PdfDocument.Page,
pageNr: Int,
yPos: Int): PdfDocument.Page
{
var lPage: PdfDocument.Page = page
var lLineCount = 34
val textPaint = TextPaint()
if (pageNr > 1) {
// close previous and start new page
mDocument.finishPage(lPage) // close this page
lPage = mDocument.startPage(pageInfo) // start new page
lLineCount = 38 // correct line count (no header so more space)
}
val canvas = lPage.canvas // init canvas
textPaint.typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)
textPaint.textSize = cNormalSize
textPaint.color = ContextCompat.getColor(mContext, R.color.black)
textPaint.isUnderlineText = false
// first build a static layout of the complete available text to determine which part fits the page
var staticLayout = StaticLayout.Builder
.obtain(spanText, 0 , spanText.length, textPaint, mPageWidth - (2 * cLeftRightMargin))
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.setLineSpacing(0f, 1.0f)
.setIncludePad(false)
.build()
// create a Rect for the available space
val r = Rect(cLeftRightMargin, yPos, (mPageWidth- (2 * cLeftRightMargin)), mPageHeight - cTopBottomMargin - yPos )
var lLastPos = try {
staticLayout.getLineBounds(lLineCount, r)
// we really do not care about the result of the above getLineBounds
// we only care if it does or doesn't raise an exception
// in case of an exception all the text is on this page and we are done.
// in case of no exception there is more text after the lineCount
staticLayout.getLineEnd(lLineCount)
} catch ( e: Exception) {
spanText.length
}
// sometimes GetLineEnd returns 0. if so all the remaining text fits
if (lLastPos == 0) lLastPos = spanText.length
// re-build the layout to contain only the part we want to print on this page
staticLayout = StaticLayout.Builder
.obtain(spanText, 0 , lLastPos, textPaint, mPageWidth - (2 * cLeftRightMargin))
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.setLineSpacing(0f, 1.0f)
.setIncludePad(false)
.build()
canvas.save()
canvas.translate(cLeftRightMargin.toFloat(), yPos.toFloat())
staticLayout.draw(canvas)
canvas.restore()
// check if we are done and if not do a recursive call to handle the remainder of the text
if (lLastPos < spanText.length) {
lPage = printLongText(pageInfo,
spanText.subSequence(lLastPos, spanText.length).toSpanned(),
lPage,
pageNr+1,
cTopBottomMargin
)
}
return lPage
}
希望这对其他人有帮助。
请随意复制并根据自己的喜好使用。