Android TextView with Clickable Links: how to capture clicks?
Based upon another answer, here's a function setTextViewHTML() which parses the links out of a HTML string and makes them clickable, and then lets you respond to the URL.
protected void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span){ int start = strBuilder.getSpanStart(span); int end = strBuilder.getSpanEnd(span); int flags = strBuilder.getSpanFlags(span); ClickableSpan clickable = new ClickableSpan() { public void onClick(View view) { // Do something with span.getURL() to handle the link click... } }; strBuilder.setSpan(clickable, start, end, flags); strBuilder.removeSpan(span);}protected void setTextViewHTML(TextView text, String html){ CharSequence sequence = Html.fromHtml(html); SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence); URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class); for(URLSpan span : urls) { makeLinkClickable(strBuilder, span); } text.setText(strBuilder); text.setMovementMethod(LinkMovementMethod.getInstance()); }
I made an easy extension function in Kotlin to catch url link clicks in a TextView by applying a new callback to URLSpan elements.
strings.xml (example link in text)
<string name="link_string">this is my link: <a href="https://www.google.com/">CLICK</a></string>
Make sure your spanned text is set to the TextView before you call "handleUrlClicks"
textView.text = getString(R.string.link_string)
This is the extension function:
/** * Searches for all URLSpans in current text replaces them with our own ClickableSpans * forwards clicks to provided function. */fun TextView.handleUrlClicks(onClicked: ((String) -> Unit)? = null) { //create span builder and replaces current text with it text = SpannableStringBuilder.valueOf(text).apply { //search for all URL spans and replace all spans with our own clickable spans getSpans(0, length, URLSpan::class.java).forEach { //add new clickable span at the same position setSpan( object : ClickableSpan() { override fun onClick(widget: View) { onClicked?.invoke(it.url) } }, getSpanStart(it), getSpanEnd(it), Spanned.SPAN_INCLUSIVE_EXCLUSIVE ) //remove old URLSpan removeSpan(it) } } //make sure movement method is set movementMethod = LinkMovementMethod.getInstance()}
This is how I call it:
textView.handleUrlClicks { url -> Timber.d("click on found span: $url")}
You've done as follows:
text_view.setMovementMethod(LinkMovementMethod.getInstance());text_view.setText( Html.fromHtml( str_links ) );
have you tried in reverse order as shown below?
text_view.setText( Html.fromHtml( str_links ) );text_view.setMovementMethod(LinkMovementMethod.getInstance());
and without:
text_view.setLinksClickable(true);