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
- Place hyperlink via SpanURL at the end of the text
- Link is clickable only in text bounds
Actual Behaviour
- If text ends with any URLSpan, link can be clicked outside text bounds (at any empty space in remain width of the element)
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
}
}
