安卓 SpannableString的使用 给文字末尾几个小尾巴

效果一:

请添加图片描述

效果二:

在这里插入图片描述

其实我们知道如果想实现效果一很简单,两个textview横向布局一下就可以了,但是如果想要是实现效果二怎么办呢。据我所知对于前端开发来说其实效果二也很简单,前端甚至可以轻松实现富文本,但是对于安卓原生开发来说,就要使用到SpannableString

代码有注释,直接上代码

1. 任何使用

                    TextView txtAuthor = new TextView(mContext);
                    txtAuthor.setText("LumoScience Publishing出版社国际版");
                    String textToAppend = " 企业 "; // 注意:这里可以添加空格,让追加的文本和前面的文本之间有间隔
                    TextUtils2.appendColoredText(txtAuthor, textToAppend);

2.TextUtils2 类


public class TextUtils2 {

    public static void appendColoredText(TextView textView, String textToAppend) {

        int textSizeSp = 12;
        int spaceW = 10;
        int backgroundDrawableResId = R.drawable.shape_tech_fillet_eight_f_three_whrith_bg;
        int textColor = Color.parseColor("#4285F5");


        // 1. 获取 txt_author 的文本
        CharSequence originalText = textView.getText();

        // 2. 创建一个新的 SpannableString,包含要追加的文本
        SpannableString spannableString = new SpannableString(textToAppend);

        // 3. 使用 DrawableBackgroundSpan 设置 Drawable 背景
        Context context = textView.getContext();
        Drawable backgroundDrawable = ContextCompat.getDrawable(context, backgroundDrawableResId);
        if (backgroundDrawable != null) {
            // 设置 Drawable 的边界,使其大小与文字大小相匹配
            int textSizePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, textSizeSp, context.getResources().getDisplayMetrics());
            int paddingLeft = 3; // 左边距
            int paddingRight = 3; // 右边距
            int paddingTop = 2; // 上边距
            int paddingBottom = 2; // 下边距
            ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(textColor);
            DrawableBackgroundSpan drawableBackgroundSpan = new DrawableBackgroundSpan(backgroundDrawable, paddingLeft, paddingRight, paddingTop, paddingBottom, foregroundColorSpan);
            spannableString.setSpan(drawableBackgroundSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        // 4. 使用 ForegroundColorSpan 设置红色文字颜色
        //ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(textColor);
        //spannableString.setSpan(foregroundColorSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // 5. 使用 AbsoluteSizeSpan 设置文字大小
        int textSizePx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, textSizeSp, context.getResources().getDisplayMetrics());
        AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(textSizePx);
        spannableString.setSpan(absoluteSizeSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // 6. 创建一个用于添加间距的 SpannableString
        SpannableString spaceSpannableString = new SpannableString(" "); // 使用一个空格作为占位符

        // 7. 创建一个空的 Drawable,并设置其宽度为 10dp
        Drawable spaceDrawable = new Drawable() {
            @Override
            public void draw(Canvas canvas) {
            }

            @Override
            public void setAlpha(int alpha) {
            }

            @Override
            public void setColorFilter(android.graphics.ColorFilter colorFilter) {
            }

            @Override
            public int getOpacity() {
                return PixelFormat.UNKNOWN;
            }
        };
        int spaceWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, spaceW, context.getResources().getDisplayMetrics());
        spaceDrawable.setBounds(0, 0, spaceWidth, 0);

        // 8. 使用 DrawableMarginSpan 设置间距
        DrawableMarginSpan spaceMarginSpan = new DrawableMarginSpan(spaceDrawable);
        spaceSpannableString.setSpan(spaceMarginSpan, 0, spaceSpannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        // 9. 将间距和追加的文本添加到 SpannableStringBuilder 中
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
        spannableStringBuilder.append(originalText);
        spannableStringBuilder.append(spaceSpannableString);
        spannableStringBuilder.append(spannableString);

        // 10. 设置 txt_author 的文本为新的 SpannableStringBuilder
        textView.setText(spannableStringBuilder);
    }
}

3. 自定义 DrawableBackgroundSpan 类


public class DrawableBackgroundSpan extends ReplacementSpan {

    private Drawable mDrawable;
    private int mPaddingLeft;
    private int mPaddingRight;
    private int mPaddingTop;
    private int mPaddingBottom;
    private ForegroundColorSpan mForegroundColorSpan;

    public DrawableBackgroundSpan(Drawable drawable, int paddingLeft, int paddingRight, int paddingTop, int paddingBottom, ForegroundColorSpan foregroundColorSpan) {
        mDrawable = drawable;
        mPaddingLeft = paddingLeft;
        mPaddingRight = paddingRight;
        mPaddingTop = paddingTop;
        mPaddingBottom = paddingBottom;
        mForegroundColorSpan = foregroundColorSpan;
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
        // 计算文字宽度
        float textWidth = paint.measureText(text, start, end);

        // 计算文字高度
        if (fm != null) {
            Paint.FontMetrics fontMetrics = paint.getFontMetrics();
            fm.ascent = (int) fontMetrics.ascent;
            fm.descent = (int) fontMetrics.descent;
            fm.top = (int) fontMetrics.top;
            fm.bottom = (int) fontMetrics.bottom;
        }

        // 返回总宽度,包括文字宽度和 padding
        return (int) (textWidth + mPaddingLeft + mPaddingRight);
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        // 计算文字宽度
        float textWidth = paint.measureText(text, start, end);

        // 计算文字高度
        Paint.FontMetricsInt fm = paint.getFontMetricsInt();
        int textHeight = fm.bottom - fm.top;

        // 计算 Drawable 的边界
        int drawableLeft = (int) x;
        int drawableTop = top + (bottom - top - textHeight) / 2 - mPaddingTop;
        int drawableRight = (int) (x + textWidth + mPaddingLeft + mPaddingRight);
        int drawableBottom = drawableTop + textHeight + mPaddingTop + mPaddingBottom;

        // 设置 Drawable 的边界
        mDrawable.setBounds(drawableLeft, drawableTop, drawableRight, drawableBottom);

        // 绘制 Drawable
        mDrawable.draw(canvas);

        // 创建一个新的 TextPaint,并应用 ForegroundColorSpan 的效果
        TextPaint textPaint = new TextPaint(paint);
        if (mForegroundColorSpan != null) {
            mForegroundColorSpan.updateDrawState(textPaint);
        }

        // 绘制文字
        int centerY = (drawableTop + drawableBottom) / 2 - (fm.bottom + fm.top) / 2;
        canvas.drawText(text, start, end, x + mPaddingLeft, centerY, textPaint);
    }
}

4. shape_tech_fillet_eight_f_three_whrith_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="3dp"/>
    <solid android:color="#144285F5"/>
    <stroke android:color="#144285F5"
        android:width="0.5dp"/>
</shape>

自己试试效果吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值