Is there a standard way to have hrefs and telephone numbers clickable in a TextView?
Asked Answered
M

1

0

I already know how to use TextView to automatically create clickable links for web addresses, phone numbers, etc.. My question is when you have HTML with hrefs in it as well as phone numbers and you want both clickable, is there a better or more standard way of doing it? Here is what I have:

String text = "Click <a href=\"http://stackoverflow.com\">Stackoverflow</a> or call 1-234-567-8901.";
TextView textView = getTextView();
textView.setLinksClickable(true);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(Html.fromHtml(text));

// This is a pretty primitive US-centric phone number REGEX but it works
Linkify.addLinks(textView, Pattern.compile("(1?[-. ])?\\d\\d\\d([-. ])\\d\\d\\d\\2\\d\\d\\d\\d"), "tel:");

This code works but doesn't seem ideal. I do NOT call setAutoLinkMask(Linkify.PHONE_NUMBERS) because it will ignore the href's in the HTML and it will wipe out the Spannables that Html.fromHtml adds even with Linkify.WEB_URLS created.

At the very least I'd like to use a more robust or standard REGEX for the phone numbers. I'm thinking something like Patterns.PHONE would at least be a better regex. However, I would hope that there is a more elegant solution that what I have above.

Mimosa answered 27/1, 2015 at 21:40 Comment(0)
G
0

You may use cutom LinkMovementMethod implementation. Like this:

public class CustomLinkMovementMethod extends LinkMovementMethod {

    private static CustomLinkMovementMethod linkMovementMethod = new BayerLinkMovementMethod();

    public boolean onTouchEvent(TextView widget, Spannable buffer,
            MotionEvent event) {
        int action = event.getAction();

        if (action == MotionEvent.ACTION_UP) {
            int x = (int) event.getX();
            int y = (int) event.getY();

            x -= widget.getTotalPaddingLeft();
            y -= widget.getTotalPaddingTop();

            x += widget.getScrollX();
            y += widget.getScrollY();

            Layout layout = widget.getLayout();
            int line = layout.getLineForVertical(y);
            int off = layout.getOffsetForHorizontal(line, x);

            URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
            if (link.length != 0) {
                String url = link[0].getURL();
                if (url.startsWith("http://") || url.startsWith("https://")) {
                    //do anything you want 
                } else if (url.startsWith("tel:")) {
                    Intent intent = new Intent(Intent.ACTION_DIAL,
                            Uri.parse(url));
                    widget.getContext().startActivity(intent);
                    return true;
                } else if (url.startsWith("mailto:")) {
                    Intent intent = new Intent(Intent.ACTION_SENDTO,
                            Uri.parse(url));
                    widget.getContext().startActivity(intent);
                    return true;
                }
                return true;
            }
        }

        return super.onTouchEvent(widget, buffer, event);
    }

    public static MovementMethod getInstance() {
        return linkMovementMethod;
    }
}
Gang answered 27/1, 2015 at 21:42 Comment(5)
This approach assumes that the Spannables are in there correctly in the first place, doesn't it?Mimosa
Well all links have to be wrapped with <a> tag I suppose. Phone numbers also.Gang
Unfortunately, I won't receive the content with the telephone numbers already wrapped.Mimosa
I thought you wrap them by yourself.Gang
I did try that already (forgot to mention that in my question) and indeed it works but that is really not any more or less standard than what I have above. Additionally, when you wrap the telephone numbers in an <a> tag, you don't need the derived LinkMovementMethod class.Mimosa

© 2022 - 2024 — McMap. All rights reserved.