You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中URLSpan置于文本末尾时点击范围超出文本边界问题

问题:URLSpan置于Spannable文本末尾时可点击范围超出文本边界

当URLSpan放在Spannable文本的末尾时,该链接的可点击范围会超出文本本身的边界,覆盖所在TextView的全部剩余空白宽度。

临时解决办法是在URLSpan后添加任意符号,但这只是权宜之计,并不完美。

预期行为

  • 在文本末尾通过URLSpan添加超链接
  • 仅文本范围内可触发链接点击

实际行为

  • 若文本以URLSpan结尾,点击TextView剩余宽度的任意空白区域都会触发链接跳转

问题示意图

解决方案:自定义LinkMovementMethod

以下是基于已采纳答案修改后的代码,通过自定义LinkMovementMethod精确控制可点击范围:

import android.text.Spannable
import android.text.SpannableString
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.view.MotionEvent
import android.widget.TextView

class CustomLinkMovementMethod : LinkMovementMethod() {
    companion object {
        private val instance = CustomLinkMovementMethod()
        fun getInstance() = instance
    }

    override fun onTouchEvent(widget: TextView?, buffer: Spannable?, event: MotionEvent?): Boolean {
        if (widget == null || event == null || buffer !is SpannableString) {
            return super.onTouchEvent(widget, buffer, event)
        }
        val action = event.action
        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) {
            val x = event.x.toInt()
            val y = event.y.toInt()
            getPressedSpan(widget, buffer, x, y)
        }
        return super.onTouchEvent(widget, buffer, event)
    }

    private fun getPressedSpan(textView: TextView, buffer: SpannableString, x: Int, y: Int): ClickableSpan? {
        val layout = textView.layout
        val line = layout.getLineForVertical(y)
        val off = layout.getOffsetForHorizontal(line, x.toFloat())

        val link = buffer.getSpans(off, off, ClickableSpan::class.java)
        return if (link.isNotEmpty()) {
            link[0]
        } else null
    }
}

内容的提问来源于stack exchange,提问作者Proxwian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:08:26