TextView that is linkified and selectable?
Asked Answered
L

3

24

I would like to have a TextView that is both selectable and linkified. When I do both I end up with selectable text but links can't be clicked.

EDIT:

I'll show the code to explain with what I struggle:

    TextView textView = view.findViewById(R.id.mytext);
    textView.setText("My text: +4412345678 Go to website: www.google.com Blah blah");
    Linkify.addLinks(textView, Linkify.ALL);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        textView.setTextIsSelectable(true);
    }
Lamppost answered 13/2, 2013 at 20:44 Comment(2)
What are you doing that isn't working? Does trying to make it linkified only work?Romanticize
When I make it linkified I can click on urls and phones. But when I make it selectable clicking is not possible anymoreLamppost
J
15

Did you try to add this on your TextView xml code?

    <TextView
    ...
    android:autoLink="all"
    android:textIsSelectable="true" />

I've tried it on my code and i can make a call/surf on web/mail and also select all text.

Jap answered 19/2, 2013 at 16:33 Comment(1)
So its just about inflating previously prepared textView (like textView = inflater.inflate(R.layout.linkify_text_view, null) ) since it doesn't work properly when adding it via code. Also check this commonsware.com/blog/2013/10/23/…Waldgrave
D
15

The autoLink attribute has an annoying bug: if you click in your example on the phone number, then return back and click on the second url link - it will open the phone number again. This attribute works so bad with multiple links, that I have implemented my own class, here is the link on Github ClickableLinksTextView.java

In your example you can replace your TextView class by my ClickableLinksTextView class in the xml-layout and change the code like this:

ClickableLinksTextView textView = (ClickableLinksTextView)view.findViewById(R.id.mytext);
textView.setText("My text: +4412345678 Go to website: www.google.com Blah blah");
Linkify.addLinks(textView, Linkify.ALL);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    textView.setMovementMethod(ArrowKeyMovementMethod.getInstance());
    textView.setTextIsSelectable(true);
    // the autoLink attribute must be removed, if you hasn't set it then ok, otherwise call textView.setAutoLink(0);
}

The original cause of the issue in your question is that the LinkMovementMethod class and the textIsSelectable attribute are not compatible at all, even Android OS developers admit this in the Android OS source code.

Do not change the movement method for text that support text selection as it would prevent an arbitrary cursor displacement.

If the text view is selectable, the only 2 correct movement method values are null and ArrowKeyMovementMethod. That's why I set ArrowKeyMovementMethod explicitly in my example, because the Linkify.addLinks sets an incorrect movement method and I should revert it.

As to the bug of the autoLink attribute, it is because android developers haven't copied link detection properly. You can look at the code example in the answer of @cheng yang, the code just takes the first link no matter how many of them you have.

Decompose answered 14/4, 2013 at 19:21 Comment(3)
textView.setMovementMethod(ArrowKeyMovementMethod.getInstance()); is what I needed to get it to work for me.Rysler
Used it together with my own URLSpans mixed with other custom spans and your class works great. Thanks for providing it! Btw there is no need to cast it explicitly to ClickableLinksTextView since the TextView api is left untouched.Addictive
The solution works. But instead of creating a custom TextView, set Linkify.addLinks(mText, Linkify.ALL); mText.setTextIsSelectable(true); mText.setMovementMethod(LinkMovementMethod.getInstance()); dynamically and remove the corresponding lines from .xml file. https://mcmap.net/q/583159/-how-set-textview-text-both-clickable-and-selectableHelbon
S
2

The problem is in Android's TextView. Calling Linkify.addLinks() would not change autolinkmask in TextView itself. I think it's an Android bug that they check mAutoLinkMask. So if you set android:autoLink in xml file, or call setAutoLinkMask() to a non 0 value, it will work.

FYI, TextView's source code:

            if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) {
            // The LinkMovementMethod which should handle taps on links has not been installed
            // on non editable text that support text selection.
            // We reproduce its behavior here to open links for these.
            ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
                    getSelectionEnd(), ClickableSpan.class);

            if (links.length > 0) {
                links[0].onClick(this);
                handled = true;
            }
        }
Saphena answered 4/3, 2013 at 0:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.