一、前言:
我們在開發(fā)中,經(jīng)常遇到一段文本,需要單獨給它部分文字設(shè)置不同的樣式,有的文字設(shè)置為粗體,有的文字設(shè)置特殊的顏色,有的地方要加入表情,遇到數(shù)學(xué)公式還可能要設(shè)置上下標,這時候該怎么辦呢?
有的人會采用不同的 TextView,這樣就可以完美解決了。先不說這個方法行不行得通,事實上,若采用這種方式,當碰上一段文字需要設(shè)置非常多的樣式時,光是這一堆TextView就夠浪費資源的了,布局還復(fù)雜,也不利于維護,因此這種方式一般不會被采用。
那么有其他辦法嗎?有,并且還很簡單,今天介紹的這個SpannableString就是用來解決這個問題的。
xml 代碼片段:
<TextView
android:id="@+id/tv_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="要變色的值"
/>
第一種方法:
//方法一:
TextView tvValue = findViewById(R.id.tv_value);
String str="默認顏色<font color='#FF0000'><small>紅顏色
</small></font>";
tvValue.setTextSize(18);
tvValue.setText(Html.fromHtml(str));
第二種方法:
采用 SpannableString實現(xiàn)
二、 SpannableString使用:
1、SpannableString、SpannableStringBuilder與String的關(guān)系
首先SpannableString、SpannableStringBuilder基本上與String差不多,也是用來存儲字符串,但它們倆的特殊就在于有一個SetSpan()函數(shù),能給這些存儲的String添加各種格式或者稱樣式(Span),將原來的String以不同的樣式顯示出來,比如在原來String上加下劃線、加背景色、改變字體顏色、用圖片把指定的文字給替換掉,等等。所以,總而言之,SpannableString、SpannableStringBuilder與String一樣, 首先也是傳字符串,但SpannableString、SpannableStringBuilder可以對這些字符串添加額外的樣式信息,但String則不行。
注意:如果這些額外信息能被所用的方式支持,比如將SpannableString傳給TextView;也有對這些額外信息不支持的,比如前一章講到的Canvas繪制文字,對于不支持的情況,SpannableString和SpannableStringBuilder就是退化為String類型,直接顯示原來的String字符串,而不會再顯示這些附加的額外信息。
2、SpannableString與SpannableStringBuilder區(qū)別
它們的區(qū)別在于 SpannableString像一個String一樣,構(gòu)造對象的時候傳入一個String,之后再無法更改String的內(nèi)容,也無法拼接多個 SpannableString;而SpannableStringBuilder則更像是StringBuilder,它可以通過其append()方法來拼接多個String;
image
3、創(chuàng)建方式
SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
設(shè)置
spannableString.setSpan(Object what, int start, int end, int flags);
這里講解一下幾個參數(shù)的意義:
- what:對SpannableString進行潤色的各種Span;
- int:需要潤色文字段開始的下標;
- end:需要潤色文字段結(jié)束的下標;
- flags:決定開始和結(jié)束下標是否包含的標志位,有四個參數(shù)可選
- SPAN_INCLUSIVE_EXCLUSIVE:包括開始下標,但不包括結(jié)束下標
- SPAN_EXCLUSIVE_INCLUSIVE:不包括開始下標,但包括結(jié)束下標
- SPAN_INCLUSIVE_INCLUSIVE:既包括開始下標,又包括結(jié)束下標
- SPAN_EXCLUSIVE_EXCLUSIVE:不包括開始下標,也不包括結(jié)束下標
這里涉及到一個重要的角色,就是各種各樣的span,它決定我們要對文字的進行怎樣的潤飾,而后三個參數(shù)決定潤飾哪些文字,為了方便起見,后面的flags默認都使用SPAN_INCLUSIVE_EXCLUSIVE模式。
3、 ForegroundColorSpan
代碼
SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
ForegroundColorSpan foregroundColorSpan1 = new ForegroundColorSpan(Color.GREEN);
ForegroundColorSpan foregroundColorSpan2 = new ForegroundColorSpan(Color.GREEN);
spannableString.setSpan(foregroundColorSpan1, 0, 2, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(foregroundColorSpan2, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);
- ForegroundColorSpan:前景色,也就是對文字上色,顏色設(shè)置為GREEN,start為4,end為7,應(yīng)該是“陳奕迅”三個字顯示為綠色。
- “如果” 也是綠色
注意:必須new兩個ForegroundColorSpan,否則只有一個地方字體變綠;
4、 BackgroudColorSpan
代碼
SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.GREEN);
spannableString.setSpan(backgroundColorSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);
BackgroudColorSpan:與ForegroundColorSpan類似,對文字背景上色
5、 AbsoluteSizeSpan
代碼
SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(40, true);
spannableString.setSpan(absoluteSizeSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);
AbsoluteSizeSpan:設(shè)置字體的相絕對大小,40表示文字大小,true表示單位為dip,若為false則表示px
6、 UnderlineSpan (下劃線)
代碼
SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
UnderlineSpan underlineSpan = new UnderlineSpan();
spannableString.setSpan(underlineSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);
UnderlineSpan:設(shè)置文字下劃線,強調(diào)突出文字時可以使用該span
7、StrikethroughSpan (中間刪除線)
代碼
SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
spannableString.setSpan(strikethroughSpan, 4, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
mTextView.setText(spannableString);
8、 SuperscriptSpan (上標)
代碼
SpannableStringBuilder spannableString = new SpannableStringBuilder("如果我是陳奕迅");
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:設(shè)置文字為上標
9、部分文字的點擊事件
效果圖:

TextView tv1 = view.findViewById(R.id.tv1);
String content = " 歡迎來到SumanSoul為了更好地向用戶提供服務(wù),未經(jīng)用戶同意,SumanSoul不會自動收集、獲取、共享或?qū)ν馓峁┯脩魝€人信息;你可以隨時查看、更正或刪除你的個人信息,SumanSoul也提供用戶注銷功能。";
tv_content.setText(content.replace(" ", ""));
SpannableStringBuilder spannableString = new SpannableStringBuilder("點擊查看完整「用戶協(xié)議」和「隱私政策」");
spannableString.setSpan(new TextAgreementClick(), 6, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new TextPrivacyClick(), 13, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
//設(shè)置點擊事件,加上這句話才有效果
tv1.setMovementMethod(LinkMovementMethod.getInstance());
//設(shè)置點擊后的顏色為透明(有默認背景)
tv1.setHighlightColor(BaseApplication.getInstance().getResources().getColor(R.color.transparent));
tv1.setText(spannableString);
<!-- 透明背景色-->
<color name="transparent" tools:ignore="MissingDefaultResource">#00000000</color>
下面是TextAgreementClick實現(xiàn)ClickableSpan
private class TextAgreementClick extends ClickableSpan{
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
//設(shè)置文本的顏色
ds.setColor(Color.RED);
//超鏈接形式的下劃線,false 表示不顯示下劃線,true表示顯示下劃線
ds.setUnderlineText(false);
}
@Override
public void onClick(View widget) {
// 執(zhí)行點擊邏輯
}
}
三、總結(jié)
- ForegroundColorSpan:前景色
- BackgroundColorSpan:背景色
- ClickableSpan:抽象類,可點擊效果,重寫onClick方法響應(yīng)點擊事件
- URLSpan:超鏈接
- MaskFilterSpan:EmbossMaskFilter浮雕效果,BlurMaskFilter模糊效果
- RelativeSpan:文字相對大小
- AbsoluteSpan:文字絕對大小
- ScaleXSpan:x軸縮放
- styleSpan:文字樣式
- TypefaceSpan:文字字體類型
- TextApearanceSpan:文字外貌
- UnderlineSpan:下劃線
- StrikeThroughSpan:刪除線
- SuperscriptSpan:上標
- SubscriptSpan:下標
- ImageSpan:圖片
這些Span能夠很好地幫助我們潤色文字,以非常簡單地方式獲得復(fù)雜和絢麗的文字效果,著實是開發(fā)中的一大利器,喜歡的朋友收藏備用吧。
