将长文本分成页面以供 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
)是可以接受的。
您可以根据您的视图或屏幕计算 pageWidth
和 pageHeight
,并且 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;
}
}
我正在 this question 中实现 messureText 方法,以便在 viewpager 中呈现之前将长文本分成具有指定大小的页面。我正在用递增的字符数做一个 while 循环来获得所需的文本块,但这似乎不是最好的解决方案。有什么建议可以提高此计算的性能吗? p/s: 我指的是 Wattpad 应用程序看到它做的非常快但不知道它是如何做的?
您可以在代码中使用 BufferedReader
。你可以把字符串留在那儿,然后在这个 reader 中传递操作。比首先从中创建一个 String 更有效。
StaticLayout or DynamicLayout 可以做到这一点。
Android 使用 (Boring
|Static
|Dynamic
)Layout 类 来测量和换行文本,这些 类 构造函数采用 CharSequence
作为输入参数,这样样式的文本(包含跨度,甚至 ImageSpan
)是可以接受的。
您可以根据您的视图或屏幕计算 pageWidth
和 pageHeight
,并且 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;
}
}