美文网首页
解决TextView的换行及ellipsize

解决TextView的换行及ellipsize

作者: 小慕汐 | 来源:发表于2016-03-30 13:55 被阅读908次

最近公司做一个社区类的应用,发现android项目中的文字排版参差不齐的情况非常严重,不得不想办法解决一下。由于之前只做过处理简单文本的这种问题,没加上含有表情、内链等处理,由于网上的各种处理办法达到的效果并不是很满易,所以只好重写来解决这个问题。

看过源码的都知道TextView里面处理换行都是在Layout里面,一般来说换行是由于英文字符及数字导致的,ellipsize则是由于计算的长度而导致...后面会显示半个字,这是android本身的一个BUG,所以经过研究找到了里面计算字符长度的方法<font color=#0099ff>Layout.getDesiredWidth</font>,方法的英文大略意思是:返回一个指定文本的宽度<font color=#ff0000>(英文略渣)</font>
由于里面的计算是用for循环计算每个CharSequence的长度,所以直接用反射通过measurePara方法来获取宽度并判断是否达到TextView的Width

onMeasure

if(mPostContentBean != null && !mPostContentBean.mParsed){
        mBuilder.clear();
        if(getWidth() != 0){
            try {
                int contentLength = getWidth() - getPaddingLeft() - getPaddingRight();
                int length = getText().length();
                
                int lines = 0;
                int start = 0;
                
                for (int i = 0; i < length; i++) {
                    int end = TextUtils.indexOf(getText(), '\n', i, length);
                    if (end < 0) 
                        i = length;
                    else
                        i = end + 1;
                    
                    for (int j = start; j <= i; j++) {
                        CharSequence sequence = getText().subSequence(start, j);
                        mTmepBuilder.clear();
                        mTmepBuilder.append(sequence);
                        if(mMaxLines == lines + 1){
                            mTmepBuilder.append(mEllipsize);
                        }
                        float w = measurePara(mTmepBuilder);
                        if (w > contentLength || j == i){
                            if(w > contentLength){
                                j--;
                            }
                            
                            end = sequence.length() - 1;
                            if(j == i){
                                end = sequence.length();
                            }
                            
                            lines++;
                            start = j;
                            mBuilder.append(sequence.subSequence(0, end));
                            if(mMaxLines == lines){
                                i = length;
                                j = i;
                                mBuilder.append(mEllipsize);
                            }
                            if(j != length && mBuilder.charAt(mBuilder.length() - 1) != '\n'){
                                mBuilder.append("\n");
                            }
                        }
                    }
                }
                mPostContentBean.mParsed = true;
                mPostContentBean.mBuilder.clear();
                mPostContentBean.mBuilder.append(mBuilder);
                setText(mBuilder);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

measurePara(SDK16以上的API是不同的)

    private float measurePara(CharSequence sequence) throws Exception{
    if(android.os.Build.VERSION.SDK_INT < 16){
        Method measurePara = Layout.class.getDeclaredMethod("measurePara", TextPaint.class, CharSequence.class, int.class, int.class);
        measurePara.setAccessible(true);
        return (Float) measurePara.invoke(null, getPaint(), mPaint, sequence, 0, sequence.length());
    }else{
        Method measurePara = Layout.class.getDeclaredMethod("measurePara", TextPaint.class, CharSequence.class, int.class, int.class);
        measurePara.setAccessible(true);
        return (Float) measurePara.invoke(null, getPaint(), sequence, 0, sequence.length());
    }
}

相关文章

网友评论

      本文标题:解决TextView的换行及ellipsize

      本文链接:https://www.haomeiwen.com/subject/cjmslttx.html