最近一直在作 TextView 富文本處理的工做,接觸到了比較纖細的粗
、字體顏色
、內聯圖片
、處理 ellipsize
、LinkMovementMethod 的坑
和ClickableSpan 的點擊事件
等問題,通過查資料
、看源碼
和作實驗
三連以後,對 Android TextView 的富文本處理有了小小的體會,寫篇博客總結下本身的收穫,往後在遇到相似問題也方便回顧。android
富文本相關的 xxxSpan
基本都在這個包下面啦,android-28
裏的有 42 個文件,包含了各式各樣設置字體
、自定義繪製
、點擊事件
、段落樣式
的 Span。canvas
多數 Span 的基類,有一個抽象方法:
public abstract void updateDrawState(TextPaint tp);
TextPaint 繼承自 Paint,這就給了咱們一個機會去操縱畫筆,設置前景色
、背景色
、字體顏色
、字體粗細
、字體大小
等等等等,想怎麼設置怎麼設置。bash
設計:這裏的用戶名要單獨加粗
我:好,加粗
設計:不行,這樣太粗了,要那種比較纖細的粗
我:我 。。。
複製代碼
Paint.setFakeBoldText
就適用於這種狀況,這個方法其實就是把畫筆變粗了而已,而不是使用粗體的字體,要更精細地控制畫筆粗細能夠用Paint.setStrokeWidth
。
附上解決問題連接: 如何實現 「中間這幾個字要加粗,可是不要太粗,比較纖細的那種粗」 ?佈局
UpdateLayout
稍後說,其餘的 Span 都實現
CharacterStyle
的
updateDrawState
方法,並對畫筆進行設置,達到變換字體外觀的目的。
增長了一個抽象方法public abstract void onClick(@NonNull View widget);
,用於響應點擊事件(須要外部配合,如 LinkMovementMethod
或OnTouchListener
)。
URLSpan
繼承自它,存儲一個 URL,點擊時用 startActivity
打開。post
UpdateAppearance
同樣是一個標識,從名字就能看出來,它還改變佈局(位置、大小等), 惟一的繼承類
MetricAffectingSpan
有一個抽象方法
public abstract void updateMeasureState(@NonNull TextPaint textPaint);
,用於改變字體的大小等屬性。
Paint
,能作的事情頗有限,
ReplacementSpan
比
MetricAffectingSpan
更進一步,直接本身接管了繪製的任務,它有兩個抽象方法
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
有很大的靈活性,想畫啥就畫啥,常常用於畫內聯的圖片之類的東西。
ParagraphStyle
相關的也有不少 Span,主要用於段落樣式的處理,我也沒用過,就不瞎說了 字體
TtsSpan
、
SuggestionSpan
、
EasyEditSpan
、
SpellCheckSpan
、
SuggestionRangeSpan
。。。
Android 提供了這麼多 Span,我平時用的比較多的也就ReplacementSpan
和ClickableSpan
,ReplacementSpan
用於現實自定義的 emoji 表情和內聯的一些小圖標之類的,ClickableSpan
則用於自定義點擊事件,好比在點擊@Somebody
、#話題#
、查看圖片
等操做時,用本地的頁面打開。這兩個 Span 用的比較多,坑也比較多,接下來會專門對這兩個 Span 作個稍微詳細的總結。
Html.fromHtml
實現的富文本處理其實也是利用 Android 提供的 Span 實現,只不過 TextView 支持的標籤十分有限,作一些簡單的處理還行,畢竟 TextView 主要顯示文本嘛,幹嗎整那麼複雜。我平時用的時候也主要是用超連接
,而後經過自定義的ClickableSpan
和Route
打開本地頁面。spa