使用 PdfDocument 类将长文本写入 pdf

问题描述 投票:0回答:1

在我的应用程序中,我可以选择将文本导出为 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)是否比可用大小长?

如何截断该点的文本并将剩余部分打印在下一页上?

我一直在寻找一种在某处设置高度的方法,但到目前为止还没有运气。

android-studio
1个回答
0
投票

经过大量尝试和转储我的应用程序,我设法找到了解决方案。 当然你可以使用一些库,但我不想要这个,因为学习它是如何工作的更有趣。所以对于所有有相同心态的人来说,我是如何解决这个问题的。

我有第一种方法,我在页面上写一个标题,然后从长文本开始。因此,在我的第一个方法中,我首先编写标题,然后调用第二个方法,该方法将作为递归调用处理长文本。
调用第二个方法很简单:

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
}

希望这对其他人有帮助。
请随意复制并根据自己的喜好使用。

© www.soinside.com 2019 - 2024. All rights reserved.