saket / Better-Link-Movement-Method

Attempts to improve how clickable links are detected, highlighted and handled in TextView
Apache License 2.0
780 stars 77 forks source link

Highlighting and clicking web links doesn't work #22

Closed j-garin closed 6 years ago

j-garin commented 6 years ago

Linkify version 2.2.0. Link text is not highlighted, click listener isn't called. Here's my code:

    <TextView
        android:id="@+id/tvLogin"
        style="?bodyText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="24dp"
        android:gravity="center_horizontal"
        android:text="@string/label_have_account" />

<string name="label_have_account">Have an account? <a href="http://www.google.com">Log in</a></string>

        BetterLinkMovementMethod.linkify(Linkify.ALL, tvLogin)
                .setOnLinkClickListener { _, _ -> navigator.login(); true }
saket commented 6 years ago

If your text contains html, consider using linkifyHtml() instead.

j-garin commented 6 years ago

@saket thank you for your replay. I already came up with this solution below. perhaps it'll be of help to you. works fine for my specific case:

internal fun TextView.linkify(listener: (String) -> Unit) {

    val spannable = (text as? Spannable) ?: SpannableString.valueOf(text)

    val urlSpans = spannable.getSpans(0, spannable.length, URLSpan::class.java)

    // loop through each span one at a time
    for (urlSpan in urlSpans) {

        // get the span range
        val start = spannable.getSpanStart(urlSpan)
        val end = spannable.getSpanEnd(urlSpan)

        // remove the bold span
        spannable.removeSpan(urlSpan)

        // add a clickable span in the same place
        val clickableSpan = ClickSpan(urlSpan.url, listener)
        spannable.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
    }

    movementMethod = LinkMovementMethod.getInstance()

}

class ClickSpan(private val url: String, private val listener: (String) -> Unit) : ClickableSpan() {
    override fun onClick(widget: View) {
        listener.invoke(url)
    }
}
saket commented 6 years ago

You don't have to do any of this. I think you will find this blog post useful: http://saket.me/html-tags-textview/