TextView, in addition to its own simple text display, can use Spanned and Html to implement a number of personalized features, such as highlighting a section of text with a partial text color and supporting click events. You can do it Spanned way.

SpannableString is a basic wrapper class for encapsulating Spanned, which can be used to add different span states using setSpan.

spannableString.setSpan(
    ClickSpan(it.content, it.color, it.clickEvent),
    0, spannableString.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
Copy the code

SpannableStringBuilder can be used to wrap multiple SpannableString objects to construct a new Spanned CharSequence literal object.

spannableStringBuilder.append(spannableString)
Copy the code

Common Spanned action classes in TextView:

  • ForegroundColorSpan Text foreground color
  • BackgroundColorSpan Text background color
  • ClickableSpan text is clickable and has clickable events
  • BlurMaskFilter Blur effect
  • StrikethroughSpan StrikethroughSpan effect
  • UnderlineSpan underlining effect
  • AbsoluteSizeSpan Absolute font size
  • RelativeSizeSpan Font relative size
  • ScaleXSpan is based on x scaling
  • StyleSpan font pattern, bold and italic
  • TextAppearanceSpan font size, style, color
  • TypefaceSpan Text font
  • URLSpan text hyperlink
  • Small scale 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= {})Copy the code

use

tvSize20.setSpannableText(
    arrayListOf(
        SpanEntity(
            // Text color
            color = Color.parseColor("#F14400"),
            // Text content
            content = "My content".// Text style
            typeface = Typeface.BOLD,
            // Whether the text supports clicking
            clickable = true.// Text click event
            clickEvent = {}
        )
        ...
    )
)
Copy the code