TextView可点击文本扩展函数

352 阅读1分钟

上班时,公司业务逻辑正好需要,顺手写得,目前只能在一串文本中加入一个可点击字符串。

/**
 * 适用于为TextView设置点击事件,且可以在点击文字后继续显示不被点击的文字
 * 不适用于一串文字中含有多处点击事件
 * @param start 点击文字的开始
 * @param end 点击文字的结束。不传递时默认为文字的末尾
 * @param color 可点击文字的颜色,默认为蓝色
 * @param setText 设置文本,如果不传递,则直接使用textView的字体
 * @param click 点击事件回调
 */
fun TextView.setClickText(
    start: Int,
    end: Int = -1,
    color: Int = Color.BLUE,
    setText: String = "",
    click: (View) -> Unit,
) {
    val text = if (setText.isBlank()) text.toString() else setText
    val endIndex = if (end == -1) text.length else end
    val unText = text.subSequence(0, start).toString()
    val clickText = text.subSequence(start, endIndex).toString()
    val overText =
        if (endIndex < text.length) text.subSequence(endIndex, text.length).toString() else ""
    setClickText(unText, clickText, color, overText, click)
}

/**
 * 不适用一串文字中有多处点击
 * @param unText 不被点击的文字
 * @param clickText 被点击的文字
 * @param color 可点击文字的颜色,默认为蓝色
 * @param overText 被点击后剩余的文字
 * @param click 点击事件回调
 */

fun TextView.setClickText(
    unText: String,
    clickText: String,
    color: Int = Color.BLUE,
    overText: String = "",
    click: (View) -> Unit
) {
    val annotatedText = buildSpannedString {
        val text = unText + clickText
        val clickableSpan = object : ClickableSpan() {
            override fun onClick(widget: View) {
                click(widget)
            }

            override fun updateDrawState(ds: TextPaint) {
                // 可点击文本不要有下划线
                ds.isUnderlineText = false
                ds.color = ds.linkColor
            }
        }
        val foreColor = ForegroundColorSpan(color)
        append(text)
        setSpan(clickableSpan, unText.length, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        setSpan(foreColor, unText.length, text.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        if (overText.isNotBlank()) {
            append(overText)
        }
    }
    movementMethod = LinkMovementMethod.getInstance()

    text = annotatedText
}