问题描述
我有一个很长的文本,我想将其分成多个页面.我还需要一种方法来设置此文本的样式.
I have a long text which I want to break into multiple pages. Also I need a way to style this text.
推荐答案
更新:我创建了示例应用a>,展示了如何使用 PageSplitter.
UPDATE: I created sample application, that shows how to use PageSplitter.
它是如何工作的?示例应用程序(俄语) - Cleverum.您只需要 PageSplitter
类.其他代码向您展示了如何使用这个类.
How it works? Example application (Russian) - Cleverum. You need only PageSplitter
class. Other code shows you how to use this class.
import android.graphics.Typeface;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.style.StyleSpan;
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 int lineSpacingExtra;
private final List<CharSequence> pages = new ArrayList<CharSequence>();
private SpannableStringBuilder currentLine = new SpannableStringBuilder();
private SpannableStringBuilder currentPage = new SpannableStringBuilder();
private int currentLineHeight;
private int pageContentHeight;
private int currentLineWidth;
private int textLineHeight;
public PageSplitter(int pageWidth, int pageHeight, float lineSpacingMultiplier, int lineSpacingExtra) {
this.pageWidth = pageWidth;
this.pageHeight = pageHeight;
this.lineSpacingMultiplier = lineSpacingMultiplier;
this.lineSpacingExtra = lineSpacingExtra;
}
public void append(String text, TextPaint textPaint) {
textLineHeight = (int) Math.ceil(textPaint.getFontMetrics(null) * lineSpacingMultiplier + lineSpacingExtra);
String[] paragraphs = text.split("
", -1);
int i;
for (i = 0; i < paragraphs.length - 1; i++) {
appendText(paragraphs[i], textPaint);
appendNewLine();
}
appendText(paragraphs[i], textPaint);
}
private void appendText(String text, TextPaint textPaint) {
String[] words = text.split(" ", -1);
int i;
for (i = 0; i < words.length - 1; i++) {
appendWord(words[i] + " ", textPaint);
}
appendWord(words[i], textPaint);
}
private void appendNewLine() {
currentLine.append("
");
checkForPageEnd();
appendLineToPage(textLineHeight);
}
private void checkForPageEnd() {
if (pageContentHeight + currentLineHeight > pageHeight) {
pages.add(currentPage);
currentPage = new SpannableStringBuilder();
pageContentHeight = 0;
}
}
private void appendWord(String appendedText, TextPaint textPaint) {
int textWidth = (int) Math.ceil(textPaint.measureText(appendedText));
if (currentLineWidth + textWidth >= pageWidth) {
checkForPageEnd();
appendLineToPage(textLineHeight);
}
appendTextToLine(appendedText, textPaint, textWidth);
}
private void appendLineToPage(int textLineHeight) {
currentPage.append(currentLine);
pageContentHeight += currentLineHeight;
currentLine = new SpannableStringBuilder();
currentLineHeight = textLineHeight;
currentLineWidth = 0;
}
private void appendTextToLine(String appendedText, TextPaint textPaint, int textWidth) {
currentLineHeight = Math.max(currentLineHeight, textLineHeight);
currentLine.append(renderToSpannable(appendedText, textPaint));
currentLineWidth += textWidth;
}
public List<CharSequence> getPages() {
List<CharSequence> copyPages = new ArrayList<CharSequence>(pages);
SpannableStringBuilder lastPage = new SpannableStringBuilder(currentPage);
if (pageContentHeight + currentLineHeight > pageHeight) {
copyPages.add(lastPage);
lastPage = new SpannableStringBuilder();
}
lastPage.append(currentLine);
copyPages.add(lastPage);
return copyPages;
}
private SpannableString renderToSpannable(String text, TextPaint textPaint) {
SpannableString spannable = new SpannableString(text);
if (textPaint.isFakeBoldText()) {
spannable.setSpan(new StyleSpan(Typeface.BOLD), 0, spannable.length(), 0);
}
return spannable;
}
}
首先,您必须创建具有 pageWidth
和 pageHeight
(以像素为单位)的 PageSplitter
对象,您可以从 View 中获取这些对象.getWidth()
和 View.getHeight()
:
First, you have to create PageSplitter
object with pageWidth
and pageHeight
(in pixels) which you can get from View.getWidth()
and View.getHeight()
:
ViewPager pagesView = (ViewPager) findViewById(R.id.pages);
PageSplitter pageSplitter = new PageSplitter(pagesView.getWidth(), pagesView.getHeight(), 1, 0);
lineSpacingMultiplier
和 lineSpacingExtra
必须与 TextView
的 lineSpacingMultiplier
和 lineSpacingExtra
属性具有相同的值code>s 将保留页面文本.
lineSpacingMultiplier
and lineSpacingExtra
must have same values as lineSpacingMultiplier
and lineSpacingExtra
attributes of TextView
s which will keep page texts.
使用 PageSplitter.append()
方法,您可以附加 text
将用 textPaint
测量:
Using PageSplitter.append()
method you can append text
which will be measured with textPaint
:
TextPaint textPaint = new TextPaint();
textPaint.setTextSize(getResources().getDimension(R.dimen.text_size));
for (int i = 0; i < 1000; i++) {
pageSplitter.append("Hello, ", textPaint);
textPaint.setFakeBoldText(true);
pageSplitter.append("world", textPaint);
textPaint.setFakeBoldText(false);
pageSplitter.append("! ", textPaint);
if ((i + 1) % 200 == 0) {
pageSplitter.append("
", textPaint);
}
}
然后通过使用 PageSplitter.getPages()
方法,您可以将原始文本拆分为页面并将每个页面放入TextView
:
Then by using PageSplitter.getPages()
method you can get original text splitted to pages and put each of them into TextView
:
pagesView.setAdapter(new TextPagerAdapter(getSupportFragmentManager(), pageSplitter.getPages()));
TextPagerAdapter:
TextPagerAdapter:
public class TextPagerAdapter extends FragmentPagerAdapter {
private final List<CharSequence> pageTexts;
public TextPagerAdapter(FragmentManager fm, List<CharSequence> pageTexts) {
super(fm);
this.pageTexts = pageTexts;
}
@Override
public Fragment getItem(int i) {
return PageFragment.newInstance(pageTexts.get(i));
}
@Override
public int getCount() {
return pageTexts.size();
}
}
页面片段:
public class PageFragment extends Fragment {
private final static String PAGE_TEXT = "PAGE_TEXT";
public static PageFragment newInstance(CharSequence pageText) {
PageFragment frag = new PageFragment();
Bundle args = new Bundle();
args.putCharSequence(PAGE_TEXT, pageText);
frag.setArguments(args);
return frag;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
CharSequence text = getArguments().getCharSequence(PAGE_TEXT);
TextView pageView = (TextView) inflater.inflate(R.layout.page, container, false);
pageView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.text_size));
pageView.setText(text);
return pageView;
}
}
其中 R.layout.page
是
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="@dimen/text_size"
android:lineSpacingMultiplier="1"
android:lineSpacingExtra="0sp">
</TextView>
PageSplitter.renderToSpannable()
方法根据 textPaint
设置将 text
包装到 SpannableString
.在当前的方法实现中,我只考虑 TextPaint.isFakeBoldText()
属性,但您也可以应用其他属性.例如,您可以将 TextPaint.getTextSize()
属性与 AbsoluteSizeSpan
一起应用.
PageSplitter.renderToSpannable()
method wraps text
to SpannableString
according to textPaint
settings. In current method implementation I consider only TextPaint.isFakeBoldText()
property, but you can also apply other properties. For example, you can apply TextPaint.getTextSize()
property with AbsoluteSizeSpan
.
这篇关于如何在 Android 中将样式文本分成页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!