Android URLSpan clickable outside of bounds

56 Views Asked by At

I've just discovered that my URLSpan at the end of Spannable is clickable outside text bounds (at full remain width of the element) if it placed right at the end of Spannable.

It can be easily fixed by adding any symbol just after the URLSpan, but does not resolve my issue completely (looks like a dog-nail in my opinion)

Expected Behaviour

  1. Place hyperlink via SpanURL at the end of the text
  2. Link is clickable only in text bounds

Actual Behaviour

  1. If text ends with any URLSpan, link can be clicked outside text bounds (at any empty space in remain width of the element)

enter image description here

Edit: My edits on an accepted @Sundar Raj answer below

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) {
            val x = event.x.toInt()
            val y = event.y.toInt()

            getPressedSpan(widget, buffer, x, y)
        } else if (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
    }
}
0

There are 0 best solutions below