我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android设置TextView样式SpannableString教程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android设置TextView样式SpannableString教程

前言

最近没什么比较好的思路,所以基本是想到什么写什么。很多人有碰到过这样的需求,展示一段文字,但是这段文字中间的几个字颜色不同,比如这样:

展示一段 这几个字颜色不同\color{red}{这几个字颜色不同}这几个字颜色不同 的文字

只是其中有一段要换文字的样式而已,其它的显示正常。有的人实现这个功能就用3个TextView去实现的,其实这是不对的,

有一些开发经验的就知道有个类是SpannableString,它能实现这个功能。

SpannableString的使用

为什么它能实现这个功能呢?其实你setTextView最终还是绘制出来,比如大家都知道Canvas是能绘制文字的,如果我用Canvas去绘制文字的话,我就很轻易能实现各种效果,包括上面的一段文字变色。其实SpannableString的效果就相当于Canvas去绘制的效果一样。

而spannableStringBuilder相对于SpannableString而言是多了拼接的效果,他们都一样,所以我这里就以spannableStringBuilder来说,如果我要使用spannableStringBuilder去实现上面的效果,可以这样写

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append(“展示一段这几个字颜色不同的文字”);
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
spannableStringBuilder.setSpan(foregroundColorSpan, 4, 11, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(spannableStringBuilder);

这样就能实现上面的效果了,我们可以简单看看ForegroundColorSpan,它有个updateDrawState方法


@Override
public void updateDrawState(@NonNull TextPaint textPaint) {
    textPaint.setColor(mColor);
}

TextPaint继承Paint,能看出这是一个设置画笔的动作。而spannableStringBuilder的setSpan方法的第一个参数就是指Span,那让我们来看看系统提供了哪些常见的Span(我这里就列举几个常用的)

  • ForegroundColorSpan:文本颜色
  • BackgroundColorSpan:背景颜色
  • AbsoluteSizeSpan:字体的大小(绝对值)
  • RelativeSizeSpan:字体的大小(相对值,xx倍)
  • StyleSpan:字体的风格
  • UnderlineSpan:下划线
  • StrikethroughSpan:删除线

除了这些之外还有RasterizerSpan、ImageSpan、TypefaceSpan等等,感兴趣的可以去看官方文档,我这就不介绍这么多了。

然后我们看setSpan的最后一个参数flags,一共有4种类型:

  • SPAN_EXCLUSIVE_EXCLUSIVE:包括前面,包括后面
  • SPAN_EXCLUSIVE_INCLUSIVE:包括前面,不包括后面
  • SPAN_INCLUSIVE_EXCLUSIVE:不包括前面,包括后面
  • SPAN_INCLUSIVE_INCLUSIVE:不包括前面,不包括后面

这是什么意思呢?看得出它的命名有两个单词_EXCLUSIVE_EXCLUSIVE这样的,第一个表示影响范围是前面,第二个表示影响范围是后面。EXCLUSIVE表示包括,INCLUSIVE表示不包括。

假如我这句话“123456”,我设置2种样式,123用ForegroundColorSpan设置字体为红色,456用BackgroundColorSpan设置背景为红色。假如123使用SPAN_EXCLUSIVE_EXCLUSIVE,456使用SPAN_INCLUSIVE_INCLUSIVE,那最终效果是123字体是红色,456字体和背景都是红色。

封装SpannableString

简单的介绍了SpannableString的作用和调用方式,我们来看看具体怎么使用,如果你按照上面的代码,每设置一个文字效果,都要写这么一串代码,那最终看起来会很臃肿

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append(“展示一段这几个字颜色不同的文字”);
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
spannableStringBuilder.setSpan(foregroundColorSpan, 4, 11, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText(spannableStringBuilder);

所以我们可以封装一下(把自己会用上的效果先整合起来)

public class SpanStringUtils {
    private Context context;
    private SpannableStringBuilder spannableStringBuilder;
    private int lp = 0;
    private int rp = 0;
    private List<Span> list = new ArrayList<>();
    public SpanStringUtils(Context context) {
        this.context = context;
        spannableStringBuilder = new SpannableStringBuilder();
    }
    public SpanStringUtils append(Span span) {
        list.add(span);
        return this;
    }
    public CharSequence create() {
        if (list == null || list.isEmpty()) {
            return null;
        }
        for (int i = 0; i < list.size(); i++) {
            Span span = list.get(i);
            createSpan(span);
        }
        return spannableStringBuilder;
    }
    private void createSpan(Span span) {
        if (span != null) {
            String str = span.textRId == -1 ? span.text : context.getString(span.textRId);
            rp = lp + str.length();
            spannableStringBuilder.append(str);
            if (span.spannable != null) {
                spannableStringBuilder.setSpan(span.spannable, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (span.textColor != -1) {
                ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(context.getResources().getColor(span.textColor));
                spannableStringBuilder.setSpan(foregroundColorSpan, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (span.backgroundColor != -1) {
                BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(context.getResources().getColor(span.backgroundColor));
                spannableStringBuilder.setSpan(backgroundColorSpan, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (span.relativeSize > 0) {
                RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(span.relativeSize);
                spannableStringBuilder.setSpan(relativeSizeSpan, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (span.xSpan > 0) {
                ScaleXSpan scaleXSpan = new ScaleXSpan(span.xSpan);
                spannableStringBuilder.setSpan(scaleXSpan, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (span.style != -1) {
                StyleSpan styleSpan = new StyleSpan(span.style);
                spannableStringBuilder.setSpan(styleSpan, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (span.isUnderline) {
                UnderlineSpan underlineSpan = new UnderlineSpan();
                spannableStringBuilder.setSpan(underlineSpan, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            if (span.isStrikethrough) {
                StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
                spannableStringBuilder.setSpan(strikethroughSpan, lp, rp, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            lp = rp;
        }
    }
    public static class Span {
        private String text;
        private int textRId = -1;
        private int textColor = -1;
        private int backgroundColor = -1;
        private float relativeSize;
        private float xSpan;
        private int style = -1;
        private boolean isUnderline;
        private boolean isStrikethrough;
        private ParcelableSpan spannable;
        public Span setText(String text) {
            this.text = text;
            return this;
        }
        public Span setText(int rId) {
            this.textRId = rId;
            return this;
        }
        public Span setTextColor(int textColor) {
            this.textColor = textColor;
            return this;
        }
        public Span setBackgroundColor(int backgroundColor) {
            this.backgroundColor = backgroundColor;
            return this;
        }
        public Span setRelativeSize(float relativeSize) {
            this.relativeSize = relativeSize;
            return this;
        }
        public Span setxSpan(float xSpan) {
            this.xSpan = xSpan;
            return this;
        }
        public Span setStyle(int style) {
            this.style = style;
            return this;
        }
        public Span setUnderline(boolean underline) {
            isUnderline = underline;
            return this;
        }
        public Span setStrikethrough(boolean strikethrough) {
            isStrikethrough = strikethrough;
            return this;
        }
        public Span setSpannable(ParcelableSpan spannable) {
            this.spannable = spannable;
            return this;
        }
    }
}

因为是用java写的,所以设置成一个链式调用的方式最终看起来会比较美观。Span表示每一段文字的效果,lp和rp是指向每段文字的范围,其它的地方应该都能很容易看懂。

然后在使用的时候这样调用

TextView testTv = findViewById(R.id.tv_test);
testTv.setTextColor(Color.parseColor("#ffffff"));
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.orange));
CharSequence charSequence = new SpanStringUtils(this)
        .append(new SpanStringUtils.Span().setText("abcde").setTextColor(R.color.blue))
        .append(new SpanStringUtils.Span().setText("qqqq").setBackgroundColor(R.color.blue))
        .append(new SpanStringUtils.Span().setText("ccc").setRelativeSize(1.5f))
        .append(new SpanStringUtils.Span().setText("dddddd"))
        .append(new SpanStringUtils.Span().setText("eee").setSpannable(foregroundColorSpan))
        .append(new SpanStringUtils.Span().setText("8s8s8s8s").setStyle(Typeface.BOLD))
        .append(new SpanStringUtils.Span().setText("kk").setUnderline(true))
        .append(new SpanStringUtils.Span().setText("M").setStrikethrough(true))
        .append(new SpanStringUtils.Span()
                .setText("LAST")
                .setTextColor(R.color.jh_orange)
                .setRelativeSize(3f)
                .setUnderline(true)
                .setStrikethrough(true))
        .create();
testTv.setText(charSequence);

前面的都是单个效果,dddddd是不设效果,最后一个是混合效果,来看看执行的结果

最后说一下,kotlin的话,不需要这样的方式,它能有更简洁的封装方式去实现这样的效果,我这里就不过多介绍了。

更多关于Android设置TextView样式的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android设置TextView样式SpannableString教程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android设置TextView样式SpannableString教程

这篇文章主要为大家介绍了Android设置TextView样式SpannableString教程示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-14

Android TextView中文字通过SpannableString设置属性用法示例

本文实例讲述了Android TextView中文字通过SpannableString设置属性的方法。分享给大家供大家参考,具体如下: 在Android中,TextView是我们最常用的用来显示文本的控件。 一般情况下,TextView中的
2022-06-06

Android TextView使用SpannableString设置复合文本的方法详解

本文实例讲述了Android TextView使用SpannableString设置复合文本的方法。分享给大家供大家参考,具体如下: TextView通常用来显示普通文本,但是有时候需要对其中某些文本进行样式、事件方面的设置。Android
2022-06-06

Android编程设置TextView颜色setTextColor用法实例

本文实例讲述了Android编程设置TextView颜色setTextColor用法。分享给大家供大家参考,具体如下: android中设置TextView的颜色有方法setTextColor,这个方法被重载了,可以传入两种参数。publi
2022-06-06

android下拉框样式怎么设置

在Android中,下拉框通常使用Spinner来实现。要设置Spinner的样式,可以通过定义一个自定义的样式来实现。以下是一个示例代码,演示如何设置Spinner的样式:在res/values/styles.xml文件中定义一个新的样式
android下拉框样式怎么设置
2024-03-04

Android程序开发之自定义设置TabHost,TabWidget样式

先看效果:京东商城底部菜单栏新浪微博底部菜单栏本次学习效果图:第一,主布局文件(启动页main.xml,位于res/layout目录下)代码
2022-06-06

Android ImageView 设置圆角及外边框样式

目录 ImageView 设置圆角及外边框样式一、设置圆角逻辑:裁剪画布二、设置外边框逻辑:在绘制 Drawable 后再绘制外边框三、在项目中集成1. 添加依赖2. 控件样式3. 在 xml 中使用(1)分别指定4个圆角的大小(2
2023-08-19

Android studio配置lambda表达式教程

Java 8的一个大亮点是引入Lambda表达式,使用它设计的代码会更加简洁。当开发者在编写Lambda表达式时,也会随之被编译成一个函数式接口。 但是目前的Android Studio还不支持Java8新特性,因此为了使用它只能曲线救国了
2023-05-31

Android编程实现TextView字体颜色设置的方法小结

本文实例讲述了Android编程实现TextView字体颜色设置的方法。分享给大家供大家参考,具体如下: 对于setTextView(int a)这里的a是传进去颜色的值。例如,红色0xff0000是指0xff0000如何直接传入R.col
2022-06-06

Android入门教程之创建样式与主题

一、前言 作为一个安卓开发者,我们一般把焦点放在app的功能上。但是仅仅有功能是不够的,界面和功能一样重要。有两种方法可以改变app的外观。第一种就是直接在xml中直接修改View的属性。这种方法只适合于只有几个View和Activity的
2022-06-06

win7怎样设置定时关机实例教程

在我们在操作电脑的情况下,有时候会出现必须按时关机,或是没有在电脑前面实际操作是必须一段时间全自动关机,可是许多电脑用户又不太喜欢组装第三方软件来进行该实际操作,那麼win7怎样设置定时关机呢?下面我给各位介绍一下win7怎样设置定时关机的
2023-07-10

discuz设置嵌入式404页面教程

discuz程序功能强大是不可否认的,但404页面的设置却是一处短缺,虽然网上有各种各样的404页面设置教程,但基本都是单独跳到一个静态的html页面,如果想要404页面跟网站其他页面一样带有顶部和底部导航,能显示用户信息怎么办呢,接下来本
2022-06-12

Android Studio 1.2版安装设置图文教程

这两天Google更新了Android Studio 1.2正式版,新版本的设置界面大变面,设置条目较旧版本进行了归类,不像以前那样列表长长的了。 趁着安装新版本的机会,把常用的设置记录一下,放到博客里面,以作备忘。 下载 正式版的Andr
2022-06-06

Android 多种简单的弹出框样式设置代码

简介 这是一个基于AlertDialog和Dialog这两个类封装的多种弹出框样式,其中提供各种简单样式的弹出框使用说明。同时也可自定义弹出框。 项目地址:http://www.github.com/jjdxmashl/jjdxm_dial
2022-06-06

windows10护眼模式如何设置windows10护眼模式设置实例教程

有的windows10客户常常在晚上应用计算机,可是长期应用对双眼又不太好,因而需要给计算机设置护眼模式,那麼应当怎么操作呢?实际上你能打开黑夜模式,这一方式也具备保护视力作用,具体步骤为:打开设置控制面板,点击系统软件进到,随后在左边挑选
2023-07-15

怎么设置微信小程序阴影样式

这篇“怎么设置微信小程序阴影样式”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么设置微信小程序阴影样式”文章吧。canva
2023-06-26

小程序怎么设置线条交点样式

本篇内容介绍了“小程序怎么设置线条交点样式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!canvasContext.setLineJoin定
2023-06-26

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录