嘗試用 Html.fromHtml("<b>Bold</b><font color='red'>Red</font>") 發現:加粗生效,但顏色不變。原因:Android Html 類支持的標籤有限,<font>、color 屬性在部分版本不支持。
Spannable 是 Android 富文本的核心,通過 Span 對象對文本區間施加樣式(顏色、字體、大小、圖片、點擊事件等)。
public static SpannableString buildStyledText(String label, String content, int labelColor, float labelSizeRatio) {
String fullText = label + " " + content;
SpannableString spannable = new SpannableString(fullText);
// 設置 label 部分顏色
spannable.setSpan(new ForegroundColorSpan(labelColor),
0, label.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 設置 label 部分字體縮放
spannable.setSpan(new RelativeSizeSpan(labelSizeRatio),
0, label.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 可繼續添加:背景色、下劃線、點擊事件、圖片等
// spannable.setSpan(new BackgroundColorSpan(Color.YELLOW), ...);
// spannable.setSpan(new UnderlineSpan(), ...);
// spannable.setSpan(new ClickableSpan() {...}, ...);
// spannable.setSpan(new ImageSpan(drawable), ...);
return spannable;
}
TextView textView = findViewById(R.id.tv_chat);
SpannableString styled = buildStyledText("系統通知:", "您有新訊息", Color.RED, 1.2f);
textView.setText(styled);
// 追加模式(聊天列表常用)
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(styled).append("\n");
textView.setText(builder);
textView.setMovementMethod(LinkMovementMethod.getInstance()); // 若含 ClickableSpan 必須設置
| Span 類 | 作用 | 示例 |
|---|---|---|
| ForegroundColorSpan | 前景色(文字顏色) | new ForegroundColorSpan(Color.RED) |
| BackgroundColorSpan | 背景色 | new BackgroundColorSpan(Color.YELLOW) |
| RelativeSizeSpan | 相對字體縮放倍數 | new RelativeSizeSpan(1.5f) |
| AbsoluteSizeSpan | 絕對字體大小 | new AbsoluteSizeSpan(20, true) |
| StyleSpan | 粗體/斜體 | new StyleSpan(Typeface.BOLD) |
| UnderlineSpan | 下劃線 | new UnderlineSpan() |
| StrikethroughSpan | 刪除線 | new StrikethroughSpan() |
| ClickableSpan | 點擊事件 | new ClickableSpan(){onClick()} |
| ImageSpan | 插入圖片/表情 | new ImageSpan(drawable) |
| URLSpan | 超鏈接 | new URLSpan("https://...") |
| TypefaceSpan | 字體族 | new TypefaceSpan("monospace") |
public class SpannableBuilder {
private final SpannableStringBuilder ssb = new SpannableStringBuilder();
public SpannableBuilder append(String text) {
ssb.append(text);
return this;
}
public SpannableBuilder color(int color) {
ssb.setSpan(new ForegroundColorSpan(color),
ssb.length() - lastTextLength, ssb.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return this;
}
// ... 其他樣式鏈式調用
public CharSequence build() { return ssb; }
}
// 使用
textView.setText(new SpannableBuilder()
.append("錯誤:").color(Color.RED).bold()
.append("網絡連接失敗").color(Color.GRAY)
.build());
TextLayoutHelper 或改用 RecyclerView + 多類型 Item 佈局。textView.setText(spannable, TextView.BufferType.SPANNABLE) 確保可編輯/可點擊。放棄 Html.fromHtml,擁抱 SpannableString:功能更強、性能更好、API 更靈活,是 Android 富文本開發的標準方式。