Linkify.addLinks(textView, Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES) not working together in Android

Viewed 559

I have HTML content that has web URLs, email addresses, and phone numbers. When I use the below code, only the email addresses are becoming links and not the web URLs. What can be the issue? I had tried with Linkify.ALL too. But didn't work.

    val htmlSpannable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY)
    } else {
        Html.fromHtml(content)
    }

    val spannableBuilder = SpannableStringBuilder(htmlSpannable)
    val bulletSpans = spannableBuilder.getSpans(
        0,
        spannableBuilder.length,
        BulletSpan::class.java
    )
    bulletSpans.forEach {
        val start = spannableBuilder.getSpanStart(it)
        val end = spannableBuilder.getSpanEnd(it)
        spannableBuilder.removeSpan(it)
        spannableBuilder.setSpan(
            ImprovedBulletSpan(bulletRadius = dip(3, context), gapWidth = dip(8, context)),
            start,
            end,
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE
        )
    }
    
    textView.text = spannableBuilder.trimEnd()
    Linkify.addLinks(textView, Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES or Linkify.PHONE_NUMBERS)
    textView.movementMethod = LinkMovementMethod.getInstance()
2 Answers

Linkify.addLinks removes existing UrlSpan, so in the given example, the links which are generated in HTML spannable get removed once Linkify is applied. However, both methods can be combined. First, converting from HTML, then saving these spans, linkify-ing to get phone numbers, etc., and re-applying HTML spans later.

Using provided example:

    val content = "<a href=\"https://www.google.com\">Google</a> <h4>3. Email us (at&nbsp;<strong>test@gmail.com</strong>)</h4>"

    //convert to html
    val htmlSpannable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY)
    } else {
        Html.fromHtml(content)
    }

    //save html spans
    val htmlUrlSpans = htmlSpannable.getSpans(0, htmlSpannable.length, URLSpan::class.java)

    //apply Linkify (resets existing Url spans)
    val linkifiedSpannable = SpannableString(htmlSpannable)
    Linkify.addLinks(linkifiedSpannable, Linkify.WEB_URLS or Linkify.EMAIL_ADDRESSES or Linkify.PHONE_NUMBERS)

    //reapply spans
    htmlUrlSpans.forEach { span ->
        val end: Int = linkifiedSpannable.getSpanEnd(span)
        val start: Int = linkifiedSpannable.getSpanStart(span)
        linkifiedSpannable.setSpan(span, start, end, 0)
    }

    //set combined one
    textView.text = linkifiedSpannable.trimEnd()
    textView.movementMethod = LinkMovementMethod.getInstance()

Removed the bullet span from example, as it's custom, so need to readd that back in.

In this scenario, it might be good to also to test further what happens if you have a link like "<a href=\"https://www.google.com\">https://www.google.com</a>", so span would be applied again.

This should work.

  1. In main.xml add a TextView text_html.

  2. Create a String html_string.

  3. In onCreate event:

a. Set the text of html_string to your text in html form with links declared in tag ( ''' Google ''' will display 'Google' in link form).

So let's set String html_string to:

<b>text_html_program: Explicit links using &lt;a&gt; markup.</b> This has markup for a <a href="http://www.google.com">link</a> specified via an &lt;a&gt; tag. Use a "tel:" URL to <a href="tel:4155551212">dial a phone number</a>

b. Display this String in TextView.

text_html.setText( Html.fromHtml(html_string));
text_html.setMovementMethod(android.text.method.LinkMovementMethod.getInstance());
Related