TextView
除了自身的简单文字展示之外,是可以使用Spanned
和 Html
实现很多个性化的功能的,比如一段文字使用中部分文字颜色高亮、支持点击事件。就可以使用Spanned
的方式实现。
SpannableString
一个最基本的用来封装Spanned
的封装类,可以用来使用setSpan
增加不同的span状态。
spannableString.setSpan(
ClickSpan(it.content, it.color, it.clickEvent),
0, spannableString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
SpannableStringBuilder
可以用来包装多个SpannableString
对象,构造出来一个新的支持Spanned
方式的CharSequence
文字对象。
spannableStringBuilder.append(spannableString)
TextView
中常见的Spanned
操作类:
- ForegroundColorSpan 文字前景颜色
- BackgroundColorSpan 文字背景色
- ClickableSpan 文字可点击、有点击事件
- BlurMaskFilter 模糊效果
- StrikethroughSpan 删除线效果
- UnderlineSpan 下划线效果
- AbsoluteSizeSpan 字体绝对大小
- RelativeSizeSpan 字体相对大小
- ScaleXSpan 基于x的缩放
- StyleSpan 字体模式、粗体、斜体
- TextAppearanceSpan 字体大小、样式、颜色
- TypefaceSpan 文字字体
- URLSpan 文本超链接
- SubscriptSpan 小标
fun TextView.setSpannableText(spanList: MutableList<SpanEntity>) {
val spannableStringBuilder = SpannableStringBuilder()
var isClickable = false
spanList.forEach {
val spannableString = SpannableString(it.content)
if (it.clickable) {
spannableString.setSpan(
ClickSpan(it.content, it.color, it.clickEvent),
0, spannableString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
isClickable = true
} else {
spannableString.setSpan(
ForegroundColorSpan(it.color),
0, spannableString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
spannableString.setSpan(
StyleSpan(it.typeface), 0,
spannableString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
spannableStringBuilder.append(spannableString)
}
this.text = spannableStringBuilder
if (isClickable) {
this.highlightColor = Color.TRANSPARENT
this.setHintTextColor(Color.TRANSPARENT)
this.movementMethod = LinkMovementMethod.getInstance()
}
}
class ClickSpan(val content: String, val color: Int, val click: (content: String) -> Unit) :
ClickableSpan() {
override fun onClick(widget: View) {
click.invoke(content)
}
override fun updateDrawState(ds: TextPaint) {
ds.color = color
ds.isUnderlineText = false
}
}
data class SpanEntity(
var color: Int,
var content: String,
val typeface: Int = Typeface.NORMAL,
var clickable: Boolean = false,
var clickEvent: (content: String) -> Unit = {}
)
使用方式
tvSize20.setSpannableText(
arrayListOf(
SpanEntity(
// 文字颜色
color = Color.parseColor("#F14400"),
// 文字内容
content = "我的内容",
// 文字样式
typeface = Typeface.BOLD,
// 文字是否支持点击
clickable = true,
// 文字点击事件
clickEvent = {}
)
...
)
)