Android之SpannableString、SpannableStringBuilder總結
SpannableString
String字串,這個咱們經常用,一定很熟悉,而這個SpanableString這個就不常用了,其實它們都可以表示字串,只不過後者可以輕鬆地利用官方提供的Api對字串進行各種風格的設定。
日常開發中都有哪些應用場景呢?比如:
- 顯示的文字加上下劃線、中劃線、斜體、加粗等
- 給TextView中部分文字加上點選事件或顏色背景
- TextView中部分文字需要顯示的字型大,部分文字需要顯示的字型小
- TextView中的文字可要求顯示錶情符號(在聊天應用中經常會出現)等等等
這點需求雖說實現起來不是什麼難事,不過選擇一個好的方案,可以事半功倍。接下來介紹今天的主角: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.
大體意思是:這是文字的類,該文字的內容是不可變的,但可以附加和分離標記物件。對於可變文字,請參見SpannableStringBuilder。
這個類原始碼很少,100行程式碼都不到,感興趣的可以去看看。其中有一個核心方法:setSpan(what,start,end,flags)共有4個引數
- what:是一個Object物件,用來設定字串的顯示風格(其中官方已經給我們提供一些常用的Span類,當然也可以自己定義了)
- sart:從字串的第幾位開始,設定的風格起作用
- end:設定的風格到第幾位後,不在起作用;其實與start構成了一個作用區間
- flags:有四種形式,就是確定作用空間是否包括收尾,待會說
常用的Span類有:
- BackgroundColorSpan 背景色
- ClickableSpan 文字可點選,有點選事件
- ForegroundColorSpan 文字顏色(前景色)
- MaskFilterSpan 修飾效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
- MetricAffectingSpan 父類,一般不用
- RasterizerSpan 光柵效果
- StrikethroughSpan 刪除線(中劃線)
- SuggestionSpan 相當於佔位符
- UnderlineSpan 下劃線
- AbsoluteSizeSpan 絕對大小(文字字型)
- DynamicDrawableSpan 設定圖片,基於文字基線或底部對齊。
- ImageSpan 圖片
- RelativeSizeSpan 相對大小(文字字型)
- ReplacementSpan 父類,一般不用
- ScaleXSpan 基於x軸縮放
- StyleSpan 字型樣式:粗體、斜體等
- SubscriptSpan 下標(數學公式會用到)
- SuperscriptSpan 上標(數學公式會用到)
- TextAppearanceSpan 文字外貌(包括字型、大小、樣式和顏色)
- TypefaceSpan 文字字型
- URLSpan 文字超連結
flags共有四種屬性:
- Spanned.SPAN_INCLUSIVE_EXCLUSIVE 從起始下標到終了下標,包括起始下標
- Spanned.SPAN_INCLUSIVE_INCLUSIVE從起始下標到終了下標,同時包括起始下標和終了下標
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE從起始下標到終了下標,但都不包括起始下標和終了下標
- Spanned.SPAN_EXCLUSIVE_INCLUSIVE 從起始下標到終了下標,包括終了下標
事例
-
ForegroundColorSpan :給一段文字中個別的字設定顏色,這個比較常用了
圖1
ForegroundColorSpan,為文字設定前景色,效果和TextView的setTextColor()類似,不過如果用setTextColor()估計得用TextView拼接或者用到Html類載入html片段實現。ForegroundColorSpan,實現如下:
TextView txtInfo = findViewById(R.id.textView); SpannableString span = new SpannableString("設定前背景色"); 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:在文字中顯示錶情符號(其實就是設定圖片)
圖2
如果對一段文字中特殊文字進行處理,就可以實現聊天效果中帶有表情符。
怎麼實現呢,程式碼如下,其實我們知道有這個用法就行了
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:可以為文字加上點選事件,比如常見的:
圖3
實現方式:
SpannableString spanStr10 = new SpannableString("請準守協議《XXXXXX協議》"); spanStr10.setSpan(new ClickableSpan() { @Override public void onClick(View view) { //點選事件 Toast.makeText(MainActivity.this,"點選了我,可以寫跳轉邏輯",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()); // 必須的設定這個,不然點選效果 不生效 tv10.setHighlightColor(Color.parseColor("#ffffff")); //點選後顯示的背景色,我這裡設定了白色,預設顏色不好看 tv10.setText(spanStr10);
還有其它一些常規用法,我就不一一列舉了,上圖:

圖3
SpanableStringBuilder
定義字串用String,對於大量字串進行拼接,我們可以使用StringBuilder進行處理;SpanableStringBuilder也是對大量SpanableString拼接進行處理的,也同樣使用append方法。舉個例子:

圖4
程式碼實現
String beforeText = "快快下單"; String afterText = "(立享200元優惠)"; 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);
後續我會繼續新增一些關於SpanableString一些Span類的用法,
github地址: https://github.com/A-How/SpanableStringDemo/tree/master