Android TextView 实现一个单词分两行显示

今天遇到一个需求,TextView实现自动换行时一个英文单词能够换行显示,使布局整齐。通过网上查询,确定实现逻辑如下:

自定义TextView,重写其onMeasure方法,在测量textView的宽高时重新拆分字符串,实现单个单词换行显示,以下是自定义TextView的源码(基本复制博客:http://www.cnblogs.com/snser/p/5159125.html中的源码):

package com.example.lupeng.customtextviewbreak;

import android.content.Context;
import android.graphics.Paint;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;


/**
 * 单个单词可以显示在两行的TextView
 * 缺点:setTextView时如果设置了SpannableString,则还需要调用本TextView的setSpan方法再次设置,而且由于Text换行导致设置Spannable时可能出现异常
 * Created by lupeng.kang on 17/1/10.
 */
public class BreakTextView extends TextView {
    private boolean mEnabled = true;

    public BreakTextView(Context context) {
        super(context);
    }

    public BreakTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public BreakTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 设置单行展示不下一个单词时是否自动截断
     *
     * @param enable
     */
    public void setAutoSplit(boolean enable) {
        mEnabled = enable;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (getWidth() > 0 && getHeight() > 0 && mEnabled) {
            CharSequence newText = autoSplitText(this);
            if (!TextUtils.isEmpty(newText)) {
                setText(newText);
            }
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 自动折断单词
     * 实现思路:测量TextView宽度时,测量每行Text的宽度,如果一行展示不下某个单词,就将这个单词折断
     *
     * @param tv
     * @return
     */
    private CharSequence autoSplitText(final TextView tv) {
        final CharSequence rawCharSequence = tv.getText();
        final String rawText = rawCharSequence.toString(); //原始文本
        final Paint tvPaint = tv.getPaint(); //paint,包含字体等信息
        final float tvWidth = tv.getWidth() - tv.getPaddingLeft() - tv.getPaddingRight(); //控件可用宽度

        //将原始文本按行拆分
        String[] rawTextLines = rawText.replaceAll("\r", "").split("\n");
        StringBuilder sbNewText = new StringBuilder();
        for (String rawTextLine : rawTextLines) {
            if (tvPaint.measureText(rawTextLine) <= tvWidth) {
                //如果整行宽度在控件可用宽度之内,就不处理了
                sbNewText.append(rawTextLine);
            } else {
                //如果整行宽度超过控件可用宽度,则按字符测量,在超过可用宽度的前一个字符处手动换行
                float lineWidth = 0;
                for (int cnt = 0; cnt != rawTextLine.length(); ++cnt) {
                    char ch = rawTextLine.charAt(cnt);
                    lineWidth += tvPaint.measureText(String.valueOf(ch));
                    if (lineWidth <= tvWidth) {
                        sbNewText.append(ch);
                    } else {
                        if (cnt - 2 >= 0 && rawTextLine.charAt(cnt - 1) >= 'A' && rawTextLine.charAt(cnt - 1) <= 'z' && rawTextLine.charAt(cnt - 2) >= 'A' && rawTextLine.charAt(cnt - 2) <= 'z') {
                            sbNewText.deleteCharAt(sbNewText.length() - 1);
                            sbNewText.append("-\n");
                            lineWidth = 0;
                            cnt -= 2;
                        } else {
                            sbNewText.append("\n");
                            lineWidth = 0;
                            --cnt;
                        }
                    }
                }
            }
            sbNewText.append("\n");
        }

        //把结尾多余的\n去掉
        if (!rawText.endsWith("\n")) {
            sbNewText.deleteCharAt(sbNewText.length() - 1);
        }
        //使用TextView设置的Span格式
        SpannableString sp = new SpannableString(sbNewText.toString());
        if (rawCharSequence instanceof Spanned) {
            TextUtils.copySpansFrom((Spanned) rawCharSequence, 0, rawCharSequence.length(), null, sp, 0);
        }

        return sp;
    }

}
接下来我们就可以像使用TextView一样使用BreakTextView了。

以上代码是复制的http://www.cnblogs.com/snser/p/5159125.html中的代码,并做了优化:

1、英文单词换行中间要加连接符 “-”,

2、autoSlitText方法返回CharSequence类型,使设定的span格式有效。

猜你喜欢

转载自blog.csdn.net/kanglupeng/article/details/54572793
今日推荐