本文介绍了如何在 Android 中将样式文本分成页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很长的文本,我想将其分成多个页面.我还需要一种方法来设置此文本的样式.

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;
    }
}

首先,您必须创建具有 pageWidthpageHeight(以像素为单位)的 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);

lineSpacingMultiplierlineSpacingExtra 必须与 TextViewlineSpacingMultiplierlineSpacingExtra 属性具有相同的值code>s 将保留页面文本.

lineSpacingMultiplier and lineSpacingExtra must have same values as lineSpacingMultiplier and lineSpacingExtra attributes of TextViews 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 中将样式文本分成页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-18 03:37