解决Android使用ClickableSpan后,会同时响应ClickableSpan和TextView的onClick事件问题

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

转载自:https://juejin.cn/post/6844903759424782344

对原作者代码做了一些修改

思路:重新实现TextView的onTouchListener


class ClickMovementMethod : View.OnTouchListener {

    private var longClickCallback: LongClickCallback? = null

    private var downTime: Long = 0

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouch(v: View, event: MotionEvent): Boolean {
        if (longClickCallback == null) {
            longClickCallback = LongClickCallback(v)
        }

        val widget = v as TextView
        // MovementMethod is set to null to prevent handling long-press events
        widget.movementMethod = null
        val text = widget.text
        val spannable = Spannable.Factory.getInstance().newSpannable(text)
        val action = event.action
        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) {
            var x = event.x.toInt()
            var y = event.y.toInt()
            x -= widget.totalPaddingLeft
            y -= widget.totalPaddingTop
            x += widget.scrollX
            y += widget.scrollY
            val layout = widget.layout
            val line = layout.getLineForVertical(y)
            val off = layout.getOffsetForHorizontal(line, x.toFloat())
            val links = spannable.getSpans(off, off, ClickableSpan::class.java)

            if (links.isNotEmpty()) {
                if (action == MotionEvent.ACTION_DOWN) {
                    downTime = SystemClock.uptimeMillis()
                    v.postDelayed(longClickCallback, ViewConfiguration.getLongPressTimeout().toLong())
                } else {
                    v.removeCallbacks(longClickCallback)
                    if (SystemClock.uptimeMillis() - downTime < ViewConfiguration.getLongPressTimeout().toLong()) {
                        links[0].onClick(widget)
                    }
                }
                return true
            }
        } else if (action == MotionEvent.ACTION_CANCEL) {
            v.removeCallbacks(longClickCallback)
        }

        return false
    }

    private class LongClickCallback(private val view: View) : Runnable {
        override fun run() {
            var v = view
            var consumed = v.performLongClick()
            while (!consumed) {
                v = v.parent as? View ?: break
                consumed = v.performLongClick()
            }
        }
    }
}

重新设置textview的onTouchListener

textView.setOnTouchListener(ClickMovementMethod())

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值