ian.shaun.thomas
ian.shaun.thomas

Reputation: 3498

Android handle HTML links and typed links in a TextView

I am trying to handle both HTML and typed links in TextViews and I am unable to find a combination of the built in tools to do this. I can make one or the other work but not both.

Given the following formats

http://google.com
<a href="http://google.com/">Google!</a>

Using .setMovementMethod(LinkMovementMethod.getInstance()) I can make the anchor tag turn into a link and open a webpage on click. Using .setAutoLinkMask(Linkify.ALL) I can make the typed link work as expected. The problem is setAutoLinkMask disables the setMovementMethod functionality and removes the highlighting it creates on the html link as well as its clicking functionality.

I tried searching for others with this issue and I believe I am being blocked by a lack of proper terms for this situation. Has anyone else come across a solution to handle both cases seamlessly?

This is what I have currently, only the typed link is linked in the TextView, the anchor just displays the text it wraps.

mTextViewBio.setText(Html.fromHtml(htmlstring));
mTextViewBio.setAutoLinkMask(Linkify.ALL);
mTextViewBio.setMovementMethod(LinkMovementMethod.getInstance());
mTextViewBio.setLinksClickable(true);

TextView output:

http://google.com
Google!

Upvotes: 2

Views: 1111

Answers (1)

abc667
abc667

Reputation: 514

Problem is that when Linify.addLinks() is called first thing what this method does is removing all spans. When you use Html.fromHtml() Spanned is return, so when Linkify parse text again firstly remove "html links". I wrote a simply class LinkifyExtra. It has one extra method

public class LinkifyExtra extends Linkify {
    public static Spanned addLinksHtmlAware(String htmlString) {
        // gather links from html
        Spanned spann = Html.fromHtml(htmlString);
        URLSpan[] old = spann.getSpans(0, spann.length(), URLSpan.class);
        List<Pair<Integer, Integer>> htmlLinks = new ArrayList<Pair<Integer, Integer>>();
        for (URLSpan span : old) {
            htmlLinks.add(new Pair<Integer, Integer>(spann.getSpanStart(span),
                    spann.getSpanEnd(span)));
        }
        // linkify spanned, html link will be lost
        Linkify.addLinks((Spannable) spann, Linkify.ALL);
        // add html links back
        for (int i = 0; i < old.length; i++) {
            ((Spannable) spann).setSpan(old[i], htmlLinks.get(i).first,
                    htmlLinks.get(i).second, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        return spann;
    }
}

and use it like that

    String htmlstring = "http://google.com <a href=\"http://google.com/\">Google!</a>";

    textView = (TextView)findViewById(R.id.textView1);

    textView.setText(LinkifyExtra.addLinksHtmlAware(htmlstring));
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    textView.setLinksClickable(true);

And it works. But you can't use mTextViewBio.setAutoLinkMask(Linkify.ALL);because it triggers addLinks() and remove "html links". Depends of what you want to do in bigger picture, this method may need some changes. I skip checking if spans are overlapping because I suppose it can't happen but if I am wrong you can simply copy this method.

Upvotes: 3

Related Questions