Span类
# Span:
---
`Span` 是强大的标记对象,可用于在字符或段落级别对文本设置样式。通过将 Span 附加到文本对象上,您能够以各种方式更改文本,包括添加颜色、使文本可点击、调整文本大小以及以自定义方式绘制文本。Span 还可以更改 TextPaint 属性、在 Canvas 上绘制,甚至更改文本布局。字体样式可设:大小、放大、前景色、背景色、正常粗体、斜体、粗斜体、下划线、删除线、上标、下标、超链接、电话邮件、网络、短信、彩信、地图、缩放、效果模糊、效果浮雕、效果插入、图片、文本、点击事件...。
Android 提供多种类型的 Span,其中涵盖各种常见的文本样式格式。您也可以创建自己的 Span,以应用自定义样式。详参[android.text.Span](https://developer.android.google.cn/guide/topics/text/spans?hl=zh)。
|类|可变文本|可变标记|数据结构|
|-|-|-|-|
|SpannedString|否|否|线性数组|
|SpannableString|否|是|线性数组|
|SpannableStringBuilder|是|是|区间树|
下面介绍如何决定使用哪个类:
- 如果您在创建后未修改文本或标记,请使用 ==SpannedString==。
- 如果您需要将少量 Span 附加到单个文本对象,并且文本本身为只读,请使用 ==SpannableString==。
- 如果您需要在创建后修改文本,并且需要将 Span 附加到文本,请使用 ==SpannableStringBuilder==。
- 如果您需要将大量 Span 附加到文本对象,则无论文本本身是否为只读,都使用 ==SpannableStringBuilder==。
---
应用 Span,请对 Spannable 对象调用 `setSpan(Object _what_, int _start_, int _end_, int _flags_)`。`what` 参数指的是要应用于文本的 Span,而 `start` 和 `end` 参数指的是要将该 Span 应用到的部分文本。
```Java
spannable = new SpannableStringBuilder("Text is spantastic!");
spannable.setSpan(
new ForegroundColorSpan(Color.RED),
8, // start
12, // end
Spannable.SPAN_EXCLUSIVE_INCLUSIVE
);
```

1. 使用 `Spannable.SPAN_EXCLUSIVE_INCLUSIVE`时,该 Span会展开以包含在 Span 边界处插入的文本;
1. 使用 `Spannable.SPAN_EXCLUSIVE_INCLUSIVE` 时, 该 Span会展开以包含其他文本。
##### `Spanable`中的常用常量:
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE — 前后都不包括 (a,b)
- Spanned.SPAN_EXCLUSIVE_INCLUSIVE — 前面不包括,后面包括 (a,b]
- Spanned.SPAN_INCLUSIVE_EXCLUSIVE — 前面包括,后面不包括 [a,b)
- Spanned.SPAN_INCLUSIVE_INCLUSIVE — 前后都包括 [a,b]
```java
//字体(default,default-bold,monospace,serif,sans-serif)
span.setSpan(new TypefaceSpan("serif"), 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
---
## android.text.style
Android 在 [++android.text.style++](https://developer.android.google.cn/reference/android/text/style/package-summary) 软件包中提供了超过 20 种 Span 类型。Android 以两种主要方式对 Span 进行分类 (跨度=Span)
|类|说明|
|-|-|
|AbsoluteSizeSpan |跨度可更改附加到其上的文本的大小。 |
|AlignmentSpan.Standard| 的默认实现AlignmentSpan。 |
|BackgroundColorSpan |更改跨度附加到的文本的背景颜色。 |
|BulletSpan| 一个将段落样式化为项目符号点的跨度(相对于布局方向)。 |
|CharacterStyle| 影响字符级文本格式的类扩展了该类。 |
|ClickableSpan |如果使用LinkMovementMethod的移动方法将此类型的对象附加到TextView的文本,则可以选择受影响的文本范围。 |
|DrawableMarginSpan |一个跨度,在其所附加的段落中添加了一个可绘制对象和一个填充。 |
|DynamicDrawableSpan| 跨度用Drawable可以与底部或周围文本的基线对齐的替换附加的文本。 |
|EasyEditSpan |提供一种简单的方法来编辑部分文本。 |
|ForegroundColorSpan |更改跨度附加到的文本的颜色。 |
|IconMarginSpan |影响跨度的段落,在文本的开头绘制一个位图。 |
|ImageSpan| 跨度用Drawable可以与底部或周围文本的基线对齐的替换附加的文本。 |
|LeadingMarginSpan.Standard |LeadingMarginSpan的标准实现,该实现调整边距但不执行任何渲染。 |
|LineBackgroundSpan.Standard |的默认实现LineBackgroundSpan,它会更改跨度所连接的行的背景颜色。 |
|LineHeightSpan.Standard |的默认实现LineHeightSpan,它会更改所附段落的行高。 |
|LocaleSpan| 更改Locale跨度附加到的文本的。 |
|MaskFilterSpan |跨度允许MaskFilter对附加的文本设置a 。 |
|MetricAffectingSpan |以改变字符宽度或高度的方式影响字符级文本格式的类扩展了该类。 |
|QuoteSpan |一个跨度,通过在文本的开头(沿布局方向)添加垂直条纹来为段落设置样式。 |
|RelativeSizeSpan |以一定比例一致地缩放附加文本的大小。 |
|ReplacementSpan ||
|ScaleXSpan |按一定比例水平缩放其所附文本的大小。 |
|StrikethroughSpan| 跨接在其附加文本上的跨度。 |
|StyleSpan |跨度允许设置其附加文本的样式。 |
|SubscriptSpan |使文本基线位置降低的跨度。 |
|SuggestionSpan |保留此范围内文本的建议候选。 |
|SuperscriptSpan |将文本基线的位置移高的跨度。 |
|TabStopSpan.Standard| TabStopSpan的默认实现,该设置允许设置制表符停止位置与文本第一行的页边距的偏移量。 |
|TextAppearanceSpan| 使用给定的TextAppearance属性设置文本外观 。 |
|Span| 一个跨度,该跨度为打算用于文本到语音引擎的关联文本提供其他元数据。 |
|TtsSpan.Builder <C扩展了 Builder <?>>|一个简单的|TtsSpans构建器。 |
|TtsSpan.CardinalBuilder |TtsSpans类型的构建器。 TtsSpan.TYPE_CARDINAL|
|TtsSpan.DateBuilder |TtsSpans类型的构建器。 TtsSpan.TYPE_DATE|
|TtsSpan.DecimalBuilder |TtsSpans类型的构建器。 TtsSpan.TYPE_DECIMAL|
|TtsSpan.DigitsBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_DIGITS|
|TtsSpan.ElectronicBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_ELECTRONIC|
|TtsSpan.FractionBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_FRACTION|
|TtsSpan.MeasureBuilder |TtsSpans类型的构建器。 TtsSpan.TYPE_MEASURE|
|TtsSpan.MoneyBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_MONEY|
|TtsSpan.OrdinalBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_ORDINAL|
|TtsSpan.SemioticClassBuilder<C extends SemioticClassBuilder<?>>| TtsSpans的构建器,具有用于句法特征的二传手。 |
|TtsSpan.TelephoneBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_TELEPHONE|
|TtsSpan.TextBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_TEXT|
|TtsSpan.TimeBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_TIME|
|TtsSpan.VerbatimBuilder| TtsSpans类型的构建器。 TtsSpan.TYPE_VERBATIM|
|TypefaceSpan |跨度,用于更新所附加文本的字体。 |
|UnderlineSpan| 跨度会突出显示其所附加的文本。 |
|URLSpan |的实施ClickableSpan,允许设置一个URL字符串。 |
---
> 范码
- ### 设置字体样式
```Java
span.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 16, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //正常
span.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 18, 20, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //粗体
span.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 20, 22, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //斜体
span.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 22, 25, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //粗斜体
text.append(span);
```
- ### 设置字体颜色
```java
//设置字体前景色
span.setSpan(new ForegroundColorSpan(Color.BLUE), 10, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//设置字体背景色
span.setSpan(new BackgroundColorSpan(Color.GREEN), 13, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 设置字体
```java
//字体(default,default-bold,monospace,serif,sans-serif)
span.setSpan(new TypefaceSpan("monospace"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new TypefaceSpan("serif"), 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 设置字体大小
```js
span.setSpan(new AbsoluteSizeSpan(20), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new AbsoluteSizeSpan(20,true), 6, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new RelativeSizeSpan(2.0f), 8, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 设置下划线
```java
span.setSpan(new UnderlineSpan(), 25, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 设置删除线
```java
span.setSpan(new StrikethroughSpan(), 28, 31, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 设置上下标
```java
span.setSpan(new SuperscriptSpan(), 31, 33, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //上标
span.setSpan(new SubscriptSpan(), 33, 35, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //下标
text.append(span);
```
- ### 设置超链接
```java
span.setSpan(new URLSpan("tel:4155551212"), 35, 40, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //电话
span.setSpan(new URLSpan("mailto:webmaster@google.com"),40, 42, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //邮件
span.setSpan(new URLSpan("http://www.baidu.com"), 42, 44, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //网络
span.setSpan(new URLSpan("sms:4155551212"), 44, 46, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //短信 使用sms:或者smsto:
span.setSpan(new URLSpan("mms:4155551212"), 46, 48, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //彩信 使用mms:或者mmsto:
span.setSpan(new URLSpan("geo:38.899533,-77.036476"), 48, 50, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //地图
text.append(span);
```
- ### 缩放效果
```java
span.setSpan(new ScaleXSpan(2.0f), 50, 54, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
ScaleXSpan()X轴方向放大为默认字体的倍数,而高度不变;2.0f 表示默认字体宽度的两倍。
```
- ### 修饰效果
```java
//模糊
span.setSpan(new MaskFilterSpan(new BlurMaskFilter(20, BlurMaskFilter.Blur.NORMAL)), 54, 58, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//浮雕
span.setSpan(new MaskFilterSpan(new EmbossMaskFilter({ 1, 1, 1 }, 0.4, 6, 3.5)), 58, 62, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 插入图片
```java
span.setSpan(new ImageSpan(this, @ic_launcher), 62, 66, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 文本点击事件
```java
click = new ClickableSpan() {
onClick(widget) {
},
updateDrawState(ds) {
ds.setColor(ds.linkColor);//设置可以点击文本部分的颜色
ds.setUnderlineText(true);//设置该文本部分是否显示超链接形式的下划线
},
};
span.setSpan(click,66, 72, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.append(span);
```
- ### 渐变色
```Java
shader = new LinearGradient(
0, 0, 0, text.getTextSize(),
Color.RED, Color.BLUE,
Shader.TileMode.CLAMP);
text.getPaint().setShader(shader);
```