需求:「我昨天已給你發郵件」——讓「昨天」顯示紅色。Android 原生 TextView 單一顏色無法滿足,核心方案是 SpannableString 配合 ForegroundColorSpan。
// Java
TextView tv = findViewById(R.id.textView);
String full = "我昨天已給你發郵件";
SpannableString spannable = new SpannableString(full);
// 關鍵字 "昨天" 起始索引 1,結束索引 3 (不含)
spannable.setSpan(new ForegroundColorSpan(Color.RED), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(spannable);
// Kotlin 擴展函數一行搞定
fun TextView.highlight(keyword: String, @ColorInt color: Int) {
val text = this.text.toString()
val start = text.indexOf(keyword)
if (start >= 0) {
val spannable = SpannableString(text)
spannable.setSpan(ForegroundColorSpan(color), start, start + keyword.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
this.text = spannable
}
}
// 呼叫:tv.highlight("昨天", Color.RED)
fun TextView.highlightAll(keywords: List, @ColorInt color: Int) {
val text = this.text.toString()
val spannable = SpannableString(text)
keywords.forEach { kw ->
var index = text.indexOf(kw)
while (index >= 0) {
spannable.setSpan(ForegroundColorSpan(color), index, index + kw.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
index = text.indexOf(kw, index + kw.length)
}
}
this.text = spannable
}
| Span 類別 | 效果 | 典型場景 |
|---|---|---|
| ForegroundColorSpan | 文字顏色 | 關鍵字高亮 |
| BackgroundColorSpan | 背景色 | 搜尋結果標記 |
| StyleSpan | 粗體/斜體 | 強調標題 |
| UnderlineSpan | 底線 | 連結樣式 |
| ClickableSpan | 可點擊+自定義事件 | @提及、#話題 |
setText(CharSequence) 而非 setText(String),否則 Span 會丟失。runOnUiThread 中設定 Span。Html.fromHtml("昨天")(API 24+ 需 FROM_HTML_MODE_LEGACY),但 Span 更靈活、效能更好。掌握SpannableString+ 各種Span組合,即可實現富文本編輯器級別的 TextView 顯示效果,是 Android UI 開發必備技能。