Android TextView 富文字之 android.text.style.xxxSpan

逗比的狼發表於2019-03-03

前言

最近一直在做 TextView 富文字處理的工作,接觸到了比較纖細的粗字型顏色內聯圖片處理 ellipsizeLinkMovementMethod 的坑ClickableSpan 的點選事件等問題,經過查資料看原始碼做實驗三連之後,對 Android TextView 的富文字處理有了小小的體會,寫篇部落格總結下自己的收穫,日後在遇到類似問題也方便回顧。

android.text.style

富文字相關的 xxxSpan 基本都在這個包下面啦,android-28 裡的有 42 個檔案,包含了各式各樣設定字型自定義繪製點選事件段落樣式的 Span。

1、CharacterStyle(來來來,你來挑畫筆)

多數 Span 的基類,有一個抽象方法:
public abstract void updateDrawState(TextPaint tp);
TextPaint 繼承自 Paint,這就給了我們一個機會去操縱畫筆,設定前景色背景色字型顏色字型粗細字型大小等等等等,想怎麼設定怎麼設定。

設計:這裡的使用者名稱要單獨加粗
我:好,加粗
設計:不行,這樣太粗了,要那種比較纖細的粗
我:我 。。。
複製程式碼

Paint.setFakeBoldText就適用於這種情況,這個方法其實就是把畫筆變粗了而已,而不是使用粗體的字型,要更精細地控制畫筆粗細可以用Paint.setStrokeWidth
附上解決問題連結: 如何實現 “中間這幾個字要加粗,但是不要太粗,比較纖細的那種粗” ?

2、UpdateAppearance

Android TextView 富文字之 android.text.style.xxxSpan
這個介面是空的,只是用來標識的,表示 Span 會改變字型的外貌(顏色、形狀等), UpdateLayout 稍後說,其他的 Span 都實現 CharacterStyleupdateDrawState 方法,並對畫筆進行設定,達到變換字型外觀的目的。

3、ClickableSpan

增加了一個抽象方法public abstract void onClick(@NonNull View widget);,用於響應點選事件(需要外部配合,如 LinkMovementMethodOnTouchListener)。
URLSpan 繼承自它,儲存一個 URL,點選時用 startActivity 開啟。

4、UpdateLayout

Android TextView 富文字之 android.text.style.xxxSpan
UpdateAppearance 一樣是一個標識,從名字就能看出來,它還改變佈局(位置、大小等), 唯一的繼承類 MetricAffectingSpan有一個抽象方法 public abstract void updateMeasureState(@NonNull TextPaint textPaint);,用於改變字型的大小等屬性。

5、ReplacementSpan (畫布給你,你行你來畫)

Android TextView 富文字之 android.text.style.xxxSpan
之前的 Span 我們只能設定 Paint,能做的事情很有限, ReplacementSpanMetricAffectingSpan更進一步,直接自己接管了繪製的任務,它有兩個抽象方法public abstract int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm);public abstract void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint);分別用於確定繪製範圍和繪製內容。這就使得ReplacementSpan有很大的靈活性,想畫啥就畫啥,經常用於畫內聯的圖片之類的東西。

6、其他的 Span

ParagraphStyle相關的也有很多 Span,主要用於段落樣式的處理,我也沒用過,就不瞎說了

Android TextView 富文字之 android.text.style.xxxSpan
還有TtsSpanSuggestionSpanEasyEditSpanSpellCheckSpanSuggestionRangeSpan 。。。

最後

Android 提供了這麼多 Span,我平時用的比較多的也就ReplacementSpanClickableSpanReplacementSpan用於現實自定義的 emoji 表情和內聯的一些小圖示之類的,ClickableSpan則用於自定義點選事件,比如在點選@Somebody#話題#檢視圖片等操作時,用本地的頁面開啟。這兩個 Span 用的比較多,坑也比較多,接下來會專門對這兩個 Span 做個稍微詳細的總結。
Html.fromHtml實現的富文字處理其實也是利用 Android 提供的 Span 實現,只不過 TextView 支援的標籤十分有限,做一些簡單的處理還行,畢竟 TextView 主要顯示文字嘛,幹嘛整那麼複雜。我平時用的時候也主要是用超連結,然後通過自定義的ClickableSpanRoute開啟本地頁面。

相關文章