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 :給一段文字中個別的字設定顏色,這個比較常用了 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:在文字中顯示錶情符號(其實就是設定圖片) 如果對一段文字中特殊文字進行處理,就可以實現聊天效果中帶有表情符。 怎麼實現呢,程式碼如下,其實我們知道有這個用法就行了
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:可以為文字加上點選事件,比如常見的: 實現方式:
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);
複製程式碼
還有其它一些常規用法,我就不一一列舉了,上圖:
github地址:github.com/A-How/Spana…SpanableStringBuilder
定義字串用String,對於大量字串進行拼接,我們可以使用StringBuilder進行處理;SpanableStringBuilder也是對大量SpanableString拼接進行處理的,也同樣使用append方法。舉個例子:
程式碼實現 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地址:github.com/A-How/Spana…