将长文本分成页面以供 viewpager 使用

Separate long text into pages for viewpager

我正在 this question 中实现 messureText 方法,以便在 viewpager 中呈现之前将长文本分成具有指定大小的页面。我正在用递增的字符数做一个 while 循环来获得所需的文本块,但这似乎不是最好的解决方案。有什么建议可以提高此计算的性能吗? p/s: 我指的是 Wattpad 应用程序看到它做的非常快但不知道它是如何做的?

您可以在代码中使用 BufferedReader。你可以把字符串留在那儿,然后在这个 reader 中传递操作。比首先从中创建一个 String 更有效。

StaticLayout or DynamicLayout 可以做到这一点。 Android 使用 (Boring|Static|Dynamic)Layout 类 来测量和换行文本,这些 类 构造函数采用 CharSequence作为输入参数,这样样式的文本(包含跨度,甚至 ImageSpan)是可以接受的。 您可以根据您的视图或屏幕计算 pageWidthpageHeight,并且 TextPaint 和两个 lineSpacing 参数必须等于您的目标 TextView,这里是我的代码:

import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
import android.text.TextPaint;

import java.util.ArrayList;
import java.util.List;

public class PageSplitter {
    private final int pageWidth;
    private final int pageHeight;
    private final float lineSpacingMultiplier;
    private final float lineSpacingExtra;
    private final List<CharSequence> pages = new ArrayList<CharSequence>();
    private SpannableStringBuilder mSpannableStringBuilder = new SpannableStringBuilder();

    public PageSplitter(int pageWidth, int pageHeight, float lineSpacingMultiplier, float lineSpacingExtra) {
        this.pageWidth = pageWidth;
        this.pageHeight = pageHeight;
        this.lineSpacingMultiplier = lineSpacingMultiplier;
        this.lineSpacingExtra = lineSpacingExtra;
    }

    public void append(CharSequence charSequence) {
        mSpannableStringBuilder.append(charSequence);
    }

    public void split(TextPaint textPaint) {
        StaticLayout staticLayout = new StaticLayout(
                mSpannableStringBuilder,
                textPaint,
                pageWidth,
                Layout.Alignment.ALIGN_NORMAL,
                lineSpacingMultiplier,
                lineSpacingExtra,
                false
        );
        int startLine = 0;
        while(startLine < staticLayout.getLineCount()) {
            int startLineTop = staticLayout.getLineTop(startLine);
            int endLine = staticLayout.getLineForVertical(startLineTop + pageHeight);
            int endLineBottom = staticLayout.getLineBottom(endLine);
            int lastFullyVisibleLine;
            if(endLineBottom > startLineTop + pageHeight)
                lastFullyVisibleLine = endLine - 1;
            else
                lastFullyVisibleLine = endLine;
            int startOffset = staticLayout.getLineStart(startLine);
            int endOffset = staticLayout.getLineEnd(lastFullyVisibleLine);
            pages.add(mSpannableStringBuilder.subSequence(startOffset, endOffset));
            startLine = lastFullyVisibleLine + 1;
        }
    }

    public List<CharSequence> getPages() {
        return pages;
    }
}