TextView 两端对齐+多余省略号显示

实现适配SpannableString的两端对齐的TextView_android textview 两端对齐_GODxxMAN的博客-CSDN博客

在此基础上增加了省略号显示 

package cn.com.ccf.rtx.widget;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.text.Layout;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;

import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

import cn.com.ccf.rtx.R;

//两端对齐
public class AlignTextView extends androidx.appcompat.widget.AppCompatTextView {
    private final String TAG = AlignTextView.class.getSimpleName();

    private boolean alignOnlyOneLine;

    public AlignTextView(Context context) {
        this(context, null);
    }

    public AlignTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AlignTextView);
        alignOnlyOneLine = typedArray.getBoolean(R.styleable.AlignTextView_alignOnlyOneLine, false);
        ColorStateList colorStateList = typedArray.getColorStateList(R.styleable.AlignTextView_android_textColor);
        setTextColor(colorStateList==null?ColorStateList.valueOf(Color.GRAY):colorStateList);

        int maxLines = typedArray.getInt(R.styleable.AlignTextView_android_maxLines, 0);

        int textSize = typedArray.getDimensionPixelSize(R.styleable.AlignTextView_android_textSize, 14);
        float textSizeSP = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, textSize, getResources().getDisplayMetrics());
        TextPaint textPaint = getPaint();
        textPaint.setTextSize(textSize);
        if (maxLines>0){
            setEllipsize(TextUtils.TruncateAt.END);
            setMaxLines(maxLines);
        }

        typedArray.recycle();
    }

    @Override
    public void setTextColor(int color) {
        super.setTextColor(color);
        getPaint().setColor(color);
    }

    @Override
    public void setTextColor(ColorStateList colors) {
        super.setTextColor(colors);
        getPaint().setColor(colors.getDefaultColor());
    }

    protected void onDraw(Canvas canvas) {
        CharSequence content = getText();
        if (content instanceof String){
            String text = (String) content;

            Layout layout = getLayout();

            for (int i = 0; i < layout.getLineCount(); ++i) {
                int lineBaseline = layout.getLineBaseline(i) + getPaddingTop();
                int lineStart = layout.getLineStart(i);
                int lineEnd = layout.getLineEnd(i);
                if (alignOnlyOneLine && layout.getLineCount() == 1) {//只有一行
                    String line = text.substring(lineStart, lineEnd);
                    float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
                   // this.drawScaledText(canvas, line, lineBaseline, width);

                    if (width > getWidth() - getPaddingLeft() - getPaddingRight()) {
                        // 文本超出控件宽度,需要绘制省略号
                        line = TextUtils.ellipsize(line, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(), TextUtils.TruncateAt.END).toString();
                        canvas.drawText(line, getPaddingLeft(), lineBaseline, getPaint());
                    } else {
                        this.drawScaledText(canvas, line, lineBaseline, width);
                    }

                } else if (i == layout.getLineCount() - 1) {//最后一行

                    //canvas.drawText(text.substring(lineStart), getPaddingLeft(), lineBaseline, getPaint());

                    String line = text.substring(lineStart);
                    float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
                    if (width > getWidth() - getPaddingLeft() - getPaddingRight()) {
                        // 文本超出控件宽度,需要绘制省略号
                        line = TextUtils.ellipsize(line, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(), TextUtils.TruncateAt.END).toString();
                        canvas.drawText(line, getPaddingLeft(), lineBaseline, getPaint());
                    } else {
                        canvas.drawText(line, getPaddingLeft(), lineBaseline, getPaint());
                    }


                    break;
                } else {//中间行
                    String line = text.substring(lineStart, lineEnd);
                    float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
                    this.drawScaledText(canvas, line, lineBaseline, width);
                }
            }

        }else if (content instanceof Spanned){
            Spanned text = (Spanned) content;

            Layout layout = getLayout();

            for (int i = 0; i < layout.getLineCount(); ++i) {
                int lineBaseline = layout.getLineBaseline(i) + getPaddingTop();
                int lineStart = layout.getLineStart(i);
                int lineEnd = layout.getLineEnd(i);
                ImageSpan[] imageSpans = text.getSpans(lineStart, lineEnd, ImageSpan.class);
                if (imageSpans.length > 0){//只适用于一张图片一行
                    imageSpans[0].draw(canvas,text,lineStart,lineEnd,getPaddingLeft(),0,0,layout.getLineBaseline(i),getSpannedPaint(text,lineStart));

                }else if (alignOnlyOneLine && layout.getLineCount() == 1) {//只有一行
                    float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
                    this.drawScaledText(canvas, text, lineStart, lineEnd, lineBaseline, width, true);

                } else if (i == layout.getLineCount() - 1) {//最后一行
                    //canvas.drawText(text, lineStart, text.length(), getPaddingLeft(), lineBaseline, getPaint());
                    float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
                    this.drawScaledText(canvas, text, lineStart, lineEnd, lineBaseline, width,false);
                    break;

                } else {//中间行
                    float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
                    boolean forceNextLine = text.charAt(lineEnd-1) == 10;
                    if (forceNextLine){
                        this.drawScaledText(canvas, text, lineStart, lineEnd, lineBaseline, width,false);
                    }else {
                        this.drawScaledText(canvas, text, lineStart, lineEnd, lineBaseline, width, true);
                    }

                }
            }

        }else {
            super.onDraw(canvas);
        }
    }

    private void drawScaledText(Canvas canvas, String line, float baseLineY, float lineWidth) {
        if (line.length() < 1) {
            return;
        }
        float x = getPaddingLeft();
        boolean forceNextLine = line.charAt(line.length() - 1) == 10;
        int length = line.length() - 1;
        if (forceNextLine || length == 0) {
            canvas.drawText(line, x, baseLineY, getPaint());
            return;
        }

        float d = (getMeasuredWidth() - lineWidth - getPaddingLeft() - getPaddingRight()) / length;

        for (int i = 0; i < line.length(); ++i) {
            String c = String.valueOf(line.charAt(i));
            float cw = StaticLayout.getDesiredWidth(c, getPaint());
            canvas.drawText(c, x, baseLineY, this.getPaint());
            x += cw + d;
        }
    }

    private void drawScaledText(Canvas canvas, Spanned text, int start, int end, float baseLineY, float lineWidth, boolean isAlign) {
        if ((end - start) < 0) {
            return;
        }

        float x = getPaddingLeft();
        int length = end - start;
        if (length == 0){
            canvas.drawText(text, start, end, x, baseLineY, getSpannedPaint(text,start));
            return;
        }

        float d;//每个字符间需要添加的间隔
        if (isAlign){
            d = (getMeasuredWidth() - lineWidth - getPaddingLeft() - getPaddingRight()) / length;
        }else {
            d = 0;
        }

        for (int i = 0; i < length; ++i) {
            float cw = StaticLayout.getDesiredWidth(text,start + i,start + i+1, getSpannedPaint(text,start + i));
            canvas.drawText(text, start + i,start + i + 1, x, baseLineY, getSpannedPaint(text,start + i));
            x += cw + d;
        }
    }

    /**
     * 获取单个字符的式样
     * @param text Spanned
     * @param index 字符的索引
     * @return TextPaint
     */
    private TextPaint getSpannedPaint(Spanned text, int index){
        TextPaint textPaint = new TextPaint();
        textPaint.set(getPaint());

        CharacterStyle[] characterSpans = text.getSpans(index, index+1, CharacterStyle.class);
        if (characterSpans.length > 0){
            for (CharacterStyle span:characterSpans){
                span.updateDrawState(textPaint);
            }
        }

        return textPaint;
    }
}

 

<declare-styleable name="AlignTextView">
    <attr name="alignOnlyOneLine" format="boolean"/>
    <attr name="android:textColor" format="color"/>
    <attr name="android:maxLines" format="integer"/>
    <attr name="android:ellipsize" format="integer"/>
    <attr name="android:textSize" format="dimension"/>

</declare-styleable>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值