Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome custom tabs and textview

I have a text view with a link inside it. In code I call the setMovementMethod to open the link when the user clicks on the text. But it opens it in the default browser or the browser chooser.

How can I use chrome custom tabs with a clickable textview?

like image 686
user3744384_ Avatar asked Nov 15 '15 11:11

user3744384_


2 Answers

This is because the TextView creates URLSpan which is ClickableSpan for each link text pattern. Once the MovementMethod finds url it calls onClick method of the URLSpan. This event starts the ACTION_VIEW intent, that's why you see the default browser starting instead.

What you could do is write your own implementation of the URLSpan, where you'd override onClick method and start the CustomTabs service from there.

First create custom URLSpan that will override onClick method:

public class CustomTabsURLSpan extends URLSpan {
    public CustomTabsURLSpan(String url) {
        super(url);
    }

    public CustomTabsURLSpan(Parcel src) {
        super(src);
    }

    @Override
    public void onClick(View widget) {
       String url = getUrl();
       //attempt to open in CustomTabs, if that fails call super.onClick(widget);
    }
}

Create custom transformation method, that will set spans to the links:

public class LinkTransformationMethod implements TransformationMethod {

    @Override
    public CharSequence getTransformation(CharSequence source, View view) {
        if (view instanceof TextView) {
            TextView textView = (TextView) view;
            Linkify.addLinks(textView, Linkify.WEB_URLS);
            String stringText = textView.getText().toString();
            Spannable text = (Spannable) textView.getText();
            URLSpan[] spans = text.getSpans(0, textView.length(), URLSpan.class);
            for (int i = spans.length - 1; i >= 0; i--) {
                URLSpan oldSpan = spans[i];
                text.removeSpan(oldSpan);
                String url = oldSpan.getURL();
                int startIndex = stringText.indexOf(url);
                int lastIndex = startIndex + url.length();
                text.setSpan(new CustomTabsURLSpan(url), startIndex, lastIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            return text;
        }
        return source;
    }

    @Override
    public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, Rect previouslyFocusedRect) {

    }
}

And here is quick explanation: https://medium.com/@nullthemall/make-textview-open-links-in-customtabs-12fdcf4bb684#.ig1chpbbe

like image 200
Nikola Despotoski Avatar answered Sep 30 '22 08:09

Nikola Despotoski


I've altered Nikola's answer a bit so that it still will work for other linkify options too.

I've added Patterns.WEB_URL.matcher() and a constructor to set which linkify options you want.

Usage:

textView.setTransformationMethod(new LinkTransformationMethod(Linkify.WEB_URLS | 
    Linkify.EMAIL_ADDRESSES | 
    Linkify.PHONE_NUMBERS));

The complete class itself:

public class LinkTransformationMethod implements TransformationMethod {

    private final int linkifyOptions;

    public LinkTransformationMethod(int linkifyOptions) {
        this.linkifyOptions = linkifyOptions;
    }

    @Override
    public CharSequence getTransformation(CharSequence source, View view) {
        if (view instanceof TextView) {
            TextView textView = (TextView) view;
            Linkify.addLinks(textView, linkifyOptions);
            if (textView.getText() == null || !(textView.getText() instanceof Spannable)) {
                return source;
            }
            Spannable text = (Spannable) textView.getText();
            URLSpan[] spans = text.getSpans(0, textView.length(), URLSpan.class);
            for (int i = spans.length - 1; i >= 0; i--) {
                URLSpan oldSpan = spans[i];
                int start = text.getSpanStart(oldSpan);
                int end = text.getSpanEnd(oldSpan);
                String url = oldSpan.getURL();
                if (!Patterns.WEB_URL.matcher(url).matches()) {
                    continue;
                }
                text.removeSpan(oldSpan);
                text.setSpan(new ChromeTabsUrlSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            return text;
        }
        return source;
    }

    @Override
    public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction, Rect previouslyFocusedRect) {

    }
}
like image 25
Boy Avatar answered Sep 30 '22 08:09

Boy