SpannableString
String字符串,這個咱們經(jīng)常用,一定很熟悉,而這個SpanableString這個就不常用了,其實它們都可以表示字符串,只不過后者可以輕松地利用官方提供的Api對字符串進(jìn)行各種風(fēng)格的設(shè)置。
日常開發(fā)中都有哪些應(yīng)用場景呢?比如:
- 顯示的文字加上下劃線、中劃線、斜體、加粗等
- 給TextView中部分文字加上點(diǎn)擊事件或顏色背景
- TextView中部分文字需要顯示的字體大,部分文字需要顯示的字體小
- TextView中的文字可要求顯示表情符號(在聊天應(yīng)用中經(jīng)常會出現(xiàn))等等等
這點(diǎn)需求雖說實現(xiàn)起來不是什么難事,不過選擇一個好的方案,可以事半功倍。接下來介紹今天的主角:SpannableString
先看看官方怎么定義這個類的
This is the class for text whose content is immutable but to which markup objects can be attached and detached. For mutable text, see SpannableStringBuilder.
大體意思是:這是文本的類,該文本的內(nèi)容是不可變的,但可以附加和分離標(biāo)記對象。對于可變文本,請參見SpannableStringBuilder。
這個類源碼很少,100行代碼都不到,感興趣的可以去看看。其中有一個核心方法:setSpan(what,start,end,flags)共有4個參數(shù)
- what:是一個Object對象,用來設(shè)置字符串的顯示風(fēng)格(其中官方已經(jīng)給我們提供一些常用的Span類,當(dāng)然也可以自己定義了)
- sart:從字符串的第幾位開始,設(shè)置的風(fēng)格起作用
- end:設(shè)置的風(fēng)格到第幾位后,不在起作用;其實與start構(gòu)成了一個作用區(qū)間
- flags:有四種形式,就是確定作用空間是否包括收尾,待會說
常用的Span類有:
- BackgroundColorSpan 背景色
- ClickableSpan 文本可點(diǎn)擊,有點(diǎn)擊事件
- ForegroundColorSpan 文本顏色(前景色)
- MaskFilterSpan 修飾效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
- MetricAffectingSpan 父類,一般不用
- RasterizerSpan 光柵效果
- StrikethroughSpan 刪除線(中劃線)
- SuggestionSpan 相當(dāng)于占位符
- UnderlineSpan 下劃線
- AbsoluteSizeSpan 絕對大小(文本字體)
- DynamicDrawableSpan 設(shè)置圖片,基于文本基線或底部對齊。
- ImageSpan 圖片
- RelativeSizeSpan 相對大?。ㄎ谋咀煮w)
- ReplacementSpan 父類,一般不用
- ScaleXSpan 基于x軸縮放
- StyleSpan 字體樣式:粗體、斜體等
- SubscriptSpan 下標(biāo)(數(shù)學(xué)公式會用到)
- SuperscriptSpan 上標(biāo)(數(shù)學(xué)公式會用到)
- TextAppearanceSpan 文本外貌(包括字體、大小、樣式和顏色)
- TypefaceSpan 文本字體
- URLSpan 文本超鏈接
flags共有四種屬性:
- Spanned.SPAN_INCLUSIVE_EXCLUSIVE 從起始下標(biāo)到終了下標(biāo),包括起始下標(biāo)
- Spanned.SPAN_INCLUSIVE_INCLUSIVE從起始下標(biāo)到終了下標(biāo),同時包括起始下標(biāo)和終了下標(biāo)
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE從起始下標(biāo)到終了下標(biāo),但都不包括起始下標(biāo)和終了下標(biāo)
- Spanned.SPAN_EXCLUSIVE_INCLUSIVE 從起始下標(biāo)到終了下標(biāo),包括終了下標(biāo)
事例
-
ForegroundColorSpan :給一段文字中個別的字設(shè)置顏色,這個比較常用了
圖1
ForegroundColorSpan,為文本設(shè)置前景色,效果和TextView的setTextColor()類似,不過如果用setTextColor()估計得用TextView拼接或者用到Html類加載html片段實現(xiàn)。ForegroundColorSpan,實現(xiàn)如下:
TextView txtInfo = findViewById(R.id.textView);
SpannableString span = new SpannableString("設(shè)置前背景色");
span.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorPrimary)),3, 5, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
txtInfo.setMovementMethod(LinkMovementMethod.getInstance());
txtInfo.setHighlightColor(getResources().getColor(android.R.color.transparent));
txtInfo.setText(span);
-
ImageSpan:在文字中顯示表情符號(其實就是設(shè)置圖片)
圖2
如果對一段文字中特殊文字進(jìn)行處理,就可以實現(xiàn)聊天效果中帶有表情符。
怎么實現(xiàn)呢,代碼如下,其實我們知道有這個用法就行了
TextView tv8 = findViewById(R.id.tv8);
SpannableString spanStr8 = new SpannableString("文字里添加表情(表情)");
Drawable image = getResources().getDrawable(R.mipmap.ic_launcher);
image.setBounds(new Rect(0,0,50,50));
spanStr8.setSpan(new ImageSpan(image),5, 7,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
tv8.setText(spanStr8);
-
ClickableSpan:可以為文字加上點(diǎn)擊事件,比如常見的:
圖3
實現(xiàn)方式:
SpannableString spanStr10 = new SpannableString("請準(zhǔn)守協(xié)議《XXXXXX協(xié)議》");
spanStr10.setSpan(new ClickableSpan() {
@Override
public void onClick(View view) {
//點(diǎn)擊事件
Toast.makeText(MainActivity.this,"點(diǎn)擊了我,可以寫跳轉(zhuǎn)邏輯",Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.parseColor("#ff4d40"));
}
},5,spanStr10.length(),Spanned.SPAN_INCLUSIVE_INCLUSIVE);
tv10.setMovementMethod(LinkMovementMethod.getInstance()); // 必須的設(shè)置這個,不然點(diǎn)擊效果 不生效
tv10.setHighlightColor(Color.parseColor("#ffffff")); //點(diǎn)擊后顯示的背景色,我這里設(shè)置了白色,默認(rèn)顏色不好看
tv10.setText(spanStr10);
還有其它一些常規(guī)用法,我就不一一列舉了,上圖:

github地址:https://github.com/A-How/SpanableStringDemo/tree/master
SpanableStringBuilder
定義字符串用String,對于大量字符串進(jìn)行拼接,我們可以使用StringBuilder進(jìn)行處理;SpanableStringBuilder也是對大量SpanableString拼接進(jìn)行處理的,也同樣使用append方法。舉個例子:

代碼實現(xiàn)
String beforeText = "快快下單";
String afterText = "(立享200元優(yōu)惠)";
int beforeSize = 20;
int afterSize = 15;
SpannableStringBuilder builder = new SpannableStringBuilder(beforeText);
builder.setSpan(new ForegroundColorSpan(Color.parseColor("#ffdf40")),0,beforeText.length(),Spanned.SPAN_INCLUSIVE_INCLUSIVE);
builder.setSpan(new AbsoluteSizeSpan(beforeSize,true),0,beforeText.length(),Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
builder.append(afterText);
builder.setSpan(new ForegroundColorSpan(Color.parseColor("#ff6940")),beforeText.length(),builder.length(),Spanned.SPAN_INCLUSIVE_INCLUSIVE);
builder.setSpan(new AbsoluteSizeSpan(afterSize,true),beforeText.length(),builder.length(),Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
tv12.setText(builder);
后續(xù)我會繼續(xù)添加一些關(guān)于SpanableString一些Span類的用法,
github地址:https://github.com/A-How/SpanableStringDemo/tree/master


