博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android UI——SpannableString详细解析
阅读量:5745 次
发布时间:2019-06-18

本文共 8670 字,大约阅读时间需要 28 分钟。

前言

相信很多朋友在日常开发中都遇到过这样的问题:有一段文本,需要单独给它各部分文字设置不同的样式,有的文字设置为粗体,有的文字设置特殊的颜色,有的地方要加入表情,遇到数学公式还可能要设置上下标,这时候该怎么办呢?

有的人可能会说:简单,不同样式的文字就用不同的TextView,这样就可以完美解决了。先不说这个方法行不行得通,事实上,若采用这种方式,当碰上一段文字需要设置非常多的样式时,光是这一堆TextView就够浪费资源的了,布局还复杂,也不利于维护,因此这种方式一般不会被采用。

那么有其他办法吗?有,并且还很简单,今天介绍的这个SpannableString就是用来解决这个问题的。

SpannableString

什么是SpannableString?

SpannableString,是CharSequence的一种,原本的CharSequence只是一串字符序列,没有任何样式,而SpannableString可以在字符序列基础上对指定的字符进行润饰,在开发中,TextView可以通过setText(CharSequence)传入SpannableString作为参数,来达到显示不同样式文字的效果。

创建方式

SpannableString spannableString = new SpannableString("如果我是陈奕迅");复制代码

如何对SpannableString进行润饰?

一般通过以下方式进行设置

spannableString.setSpan(Object what, int start, int end, int flags);复制代码

这里讲解一下几个参数的意义

  • what:对SpannableString进行润色的各种Span;
  • int:需要润色文字段开始的下标;
  • end:需要润色文字段结束的下标;
  • flags:决定开始和结束下标是否包含的标志位,有四个参数可选
    • SPAN_INCLUSIVE_EXCLUSIVE:包括开始下标,但不包括结束下标
    • SPAN_EXCLUSIVE_INCLUSIVE:不包括开始下标,但包括结束下标
    • SPAN_INCLUSIVE_INCLUSIVE:既包括开始下标,又包括结束下标
    • SPAN_EXCLUSIVE_EXCLUSIVE:不包括开始下标,也不包括结束下标

这里涉及到一个重要的角色,就是各种各样的span,它决定我们要对文字的进行怎样的润饰,而后三个参数决定润饰哪些文字,为了方便起见,后面的flags默认都使用SPAN_INCLUSIVE_EXCLUSIVE模式。

各种Span

先来看一张类结构图,了解各种Span之间的关系

可以看出所有Span都继承于CharacterStyle这个抽象类,另外MetricAffectingSpan、ReplacementSpan和ClickableSpan都是抽象类,下面展示一些常用的Span

ForegroundColorSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.GREEN);spannableString.setSpan(foregroundColorSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

ForegroundColorSpan:前景色,也就是对文字上色,颜色设置为GREEN,start为4,end为7,应该是“陈奕迅”三个字显示为绿色,看一下实际效果

BackgroudColorSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.GREEN);spannableString.setSpan(backgroundColorSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

BackgroudColorSpan:与ForegroundColorSpan类似,对文字背景上色

ClickableSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");ClickableSpan clickableSpan = new ClickableSpan() {    @Override    public void onClick(View widget) {        Toast.makeText(MainActivity.this, "如果我是陈奕迅", Toast.LENGTH_SHORT).show();    }    @Override    public void updateDrawState(TextPaint ds) {        ds.setUnderlineText(false);    }};spannableString.setSpan(clickableSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setMovementMethod(LinkMovementMethod.getInstance());mTextView.setText(spannableString);复制代码

ClickableSpan:是一个抽象类,实现可点击效果,可以重写onClick方法实现点击事件,这里点击“陈奕迅”三个字简单地弹toast

URLSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");URLSpan urlSpan = new URLSpan("https://www.baidu.com/s?ie=UTF-8&wd=陈奕迅");spannableString.setSpan(urlSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setMovementMethod(LinkMovementMethod.getInstance());mTextView.setText(spannableString);复制代码

URLSpan:实现超链接的效果,继承于ClickableSpan,点击实现跳转到浏览器

MaskFilterSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");MaskFilterSpan embossMaskFilterSpan =    new MaskFilterSpan(new EmbossMaskFilter(new float[]{10, 10, 10}, 0.5f, 1, 1));spannableString.setSpan(embossMaskFilterSpan, 0, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(1.5f);spannableString.setSpan(relativeSizeSpan, 0, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);MaskFilterSpan blurMaskFilterSpan = new MaskFilterSpan(new BlurMaskFilter(10, Blur.NORMAL));spannableString.setSpan(blurMaskFilterSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

MaskFilterSpan:构造方法接受MaskFilter作为参数,其中它有两个子类:EmbossMaskFilter和BlurMaskFilter

EmbossMaskFilter实现浮雕效果

EmbossMaskFilter(float[] direction, float ambient, float specular, float blurRadius)复制代码
  • direction:float数组,定义长度为3的数组标量[x,y,z],来指定光源的方向
  • ambient:环境光亮度,0~1
  • specular:镜面反射系数
  • blurRadius:模糊半径,必须>0

BlurMaskFilter实现模糊效果

BlurMaskFilter(float radius, Blur style)复制代码
  • radius:模糊半径
  • style:有四个参数可选
    • BlurMaskFilter.Blur.NORMAL:内外模糊
    • BlurMaskFilter.Blur.OUTER:外部模糊
    • BlurMaskFilter.Blur.INNER:内部模糊
    • BlurMaskFilter.Blur.SOLID:内部加粗,外部模糊

RelativeSizeSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(1.5f);spannableString.setSpan(relativeSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

RelativeSizeSpan:设置字体的相对大小,这里设置为TextView大小的1.5倍,看图

AbsoluteSizeSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(40, true);spannableString.setSpan(absoluteSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

AbsoluteSizeSpan:设置字体的相绝对大小,40表示文字大小,true表示单位为dip,若为false则表示px

ScaleXSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");ScaleXSpan scaleXSpan= new ScaleXSpan(1.5f);spannableString.setSpan(scaleXSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

ScaleXSpan:设置字体x轴缩放,1.5表示x轴放大为1.5倍,效果如图

StyleSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);StyleSpan italicSpan = new StyleSpan(Typeface.ITALIC);StyleSpan boldItalicSpan = new StyleSpan(Typeface.BOLD_ITALIC);spannableString.setSpan(boldSpan, 0, 2, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);spannableString.setSpan(italicSpan, 2, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);spannableString.setSpan(boldItalicSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

StyleSpan:设置文字样式,如斜体、粗体

TypefaceSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");TypefaceSpan monospace = new TypefaceSpan("monospace");TypefaceSpan serif = new TypefaceSpan("serif");TypefaceSpan sans_serif = new TypefaceSpan("sans-serif");spannableString.setSpan(monospace, 0, 2, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);spannableString.setSpan(serif, 2, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);spannableString.setSpan(sans_serif, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

TypefaceSpan:设置文字字体类型,如monospace、serif和sans-serif等等

TextAppearanceSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(this, android.R.style.TextAppearance_Material);spannableString.setSpan(textAppearanceSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

TextAppearanceSpan:设置文字外貌,通过style资源设置,这里使用系统的style资源

UnderlineSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");UnderlineSpan underlineSpan = new UnderlineSpan();spannableString.setSpan(underlineSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

UnderlineSpan:设置文字下划线,强调突出文字时可以使用该span

StrikethroughSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");StrikethroughSpan strikethroughSpan = new StrikethroughSpan();spannableString.setSpan(strikethroughSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

StrikethroughSpan:设置文字删除线

SuperscriptSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");SuperscriptSpan superscriptSpan = new SuperscriptSpan();RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(0.8f);spannableString.setSpan(relativeSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);spannableString.setSpan(superscriptSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

SuperscriptSpan:设置文字为上标

SubscriptSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");SubscriptSpan subscriptSpan = new SubscriptSpan();RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(0.8f);spannableString.setSpan(relativeSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);spannableString.setSpan(subscriptSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

SubscriptSpan:设置文字为下标

ImageSpan

代码

SpannableString spannableString = new SpannableString("如果我是陈奕迅");ImageSpan imageSpan = new ImageSpan(this, R.drawable.ic_eason);spannableString.setSpan(imageSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);mTextView.setText(spannableString);复制代码

ImageSpan:设置图片

总结

总结一下以上提到的Span

  • ForegroundColorSpan:前景色
  • BackgroundColorSpan:背景色
  • ClickableSpan:抽象类,可点击效果,重写onClick方法响应点击事件
  • URLSpan:超链接
  • MaskFilterSpan:EmbossMaskFilter浮雕效果,BlurMaskFilter模糊效果
  • RelativeSpan:文字相对大小
  • AbsoluteSpan:文字绝对大小
  • ScaleXSpan:x轴缩放
  • styleSpan:文字样式
  • TypefaceSpan:文字字体类型
  • TextApearanceSpan:文字外貌
  • UnderlineSpan:下划线
  • StrikeThroughSpan:删除线
  • SuperscriptSpan:上标
  • SubscriptSpan:下标
  • ImageSpan:图片

这些Span能够很好地帮助我们润色文字,以非常简单地方式获得复杂和绚丽的文字效果,着实是开发中的一大利器,喜欢的朋友收藏备用吧

感谢阅读!

欢迎关注个人微信公众号:Charming写字的地方

转载地址:http://snazx.baihongyu.com/

你可能感兴趣的文章
F#初学笔记06
查看>>
实战:将企业域名解析委派给企业DNS服务器
查看>>
在Lync 2013环境部署Office Web Apps
查看>>
微软大会Ignite,你准备好了么?
查看>>
读书笔记-高标管事 低调管人
查看>>
Master带给世界的思考:是“失控”还是进化
查看>>
用户和开发者不满苹果iCloud问题多多
查看>>
java.lang.UnsatisfiedLinkError:no dll in java.library.path终极解决之道
查看>>
我的工具:文本转音频文件
查看>>
【许晓笛】从零开始运行EOS系统
查看>>
【跃迁之路】【460天】程序员高效学习方法论探索系列(实验阶段217-2018.05.11)...
查看>>
C++入门读物推荐
查看>>
TiDB 源码阅读系列文章(七)基于规则的优化
查看>>
面试中会遇到的正则题
查看>>
Spring之旅第八站:Spring MVC Spittr舞台的搭建、基本的控制器、请求的输入、表单验证、测试(重点)...
查看>>
数据结构与算法——常用排序算法及其Java实现
查看>>
你所不知的Webpack-多种配置方法
查看>>
React.js 集成 Kotlin Spring Boot 开发 Web 应用实例详解
查看>>
webpack+typescript+threejs+vscode开发
查看>>
python读excel写入mysql小工具
查看>>