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

server/2025/2/26 15:28:09/

效果一:

请添加图片描述

效果二:

在这里插入图片描述

其实我们知道如果想实现效果一很简单,两个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. 创建一个用于添加间距的 SpannableStringSpannableString spaceSpannableString = new SpannableString(" "); // 使用一个空格作为占位符// 7. 创建一个空的 Drawable,并设置其宽度为 10dpDrawable spaceDrawable = new Drawable() {@Overridepublic void draw(Canvas canvas) {}@Overridepublic void setAlpha(int alpha) {}@Overridepublic void setColorFilter(android.graphics.ColorFilter colorFilter) {}@Overridepublic 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 的文本为新的 SpannableStringBuildertextView.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;}@Overridepublic 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;}// 返回总宽度,包括文字宽度和 paddingreturn (int) (textWidth + mPaddingLeft + mPaddingRight);}@Overridepublic 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);// 绘制 DrawablemDrawable.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>

自己试试效果吧


http://www.ppmy.cn/server/170781.html

相关文章

Java面试题整理一(反射)

问题&#xff1a;简述Java中的反射使用 答&#xff1a; 1.作用&#xff1a; 可以通过配置文件来动态配置和加载类&#xff0c;以实现软件工程理论里所提及的类与类&#xff0c;模块与模块之间的解耦。反射最经典的应用是spring框架。 2. 定义 反射简单来说&#xff0c;就是…

DeepSeek-R1 满血版和蒸馏版鉴别方法

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法Q大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第名。授权多项发明专利。对机器学…

Transceivers Wizard IP核

Transceivers Wizard IP核 1. 基础配置&#xff08;Basic Configuration&#xff09; 1.1 收发器类型&#xff08;Transceiver Type&#xff09; 选项&#xff1a;GTP、GTX、GTH、GTZ&#xff08;根据具体FPGA型号选择&#xff09;。 GTP&#xff1a;低功耗&#xff0c;适用于…

AGI分级探索:从OpenAI到DeepMind,展望未来AI图景

AGI分级探索&#xff1a;从OpenAI到DeepMind&#xff0c;展望未来AI图景 | AI大咖说 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;通用人工智能&#xff08;AGI&#xff09;这一概念逐渐走入大众视野。AGI指的是能够像人类一样具备广泛智能的人工系统&a…

DeepSeek 与后端开发:AI 赋能云端架构与智能化服务

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;后端开发正经历一场深刻变革。从传统的 REST API 到…

理解 “边缘计算“

边缘计算&#xff08;Edge Computing&#xff09;是一种将数据处理和计算能力靠近数据源的新型计算模式&#xff0c;在工业物联网&#xff08;IIoT&#xff09;等众多领域有着至关重要的作用&#xff0c;以下为你详细介绍&#xff1a; 定义 边缘计算是指在靠近物或数据源头的…

学习threejs,使用MeshBasicMaterial基本网格材质

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshBasicMaterial 二…

JavaScript循环陷阱:forEach与for循环中return的差异解析

JavaScript循环陷阱&#xff1a;forEach与for循环中return的差异解析 &#x1f4cc; 核心问题重现 // for循环示例 function findWithFor() {const arr [1, 2, 3];for (let i 0; i < arr.length; i) {if (arr[i] 2) return Found!; // 立即终止} }// forEach示例 func…