Link text 的字符串资源。Android 突出显示 TextView 中的链接,但它们不响应点击。我究竟做错了什么?我必须在我的活动中为 TextView 设置一个 onClickListener 吗?看起来它与我定义字符串资源的方式有关。这不起作......" /> Link text 的字符串资源。Android 突出显示 TextView 中的链接,但它们不响应点击。我究竟做错了什么?我必须在我的活动中为 TextView 设置一个 onClickListener 吗?看起来它与我定义字符串资源的方式有关。这不起作......"> Link text 的字符串资源。Android 突出显示 TextView 中的链接,但它们不响应点击。我究竟做错了什么?我必须在我的活动中为 TextView 设置一个 onClickListener 吗?看起来它与我定义字符串资源的方式有关。这不起作......" />
ChatGPT解决这个技术问题 Extra ChatGPT

How to make links in a TextView clickable

I have the following TextView defined:

<TextView 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:text="@string/txtCredits"
    android:autoLink="web" android:id="@+id/infoTxtCredits"
    android:layout_centerInParent="true"
    android:linksClickable="true"></TextView>

where @string/txtCredits is a string resource that contains <a href="some site">Link text</a>.

Android is highlighting the links in the TextView, but they do not respond to clicks. What am I doing wrong? Do I have to set an onClickListener for the TextView in my activity for something as simple as this?

It looks like it has to do with the way I define my string resource.

This does not work:

<string name="txtCredits"><a href="http://www.google.com">Google</a></string>

But this does:

<string name="txtCredits">www.google.com</string>

Which is a bummer because I would much rather show a text link than show the full URL.

android:autoLink="web" this is the main line needs to be added to xml and it works like charm. thanks @Richard
<string name="txtCredits"><a href="google.com">www.google.com</a></string> use the above sttring and it works. It is learnt that the string in href and with in anchor tag must be same and have .com or .* to work need to check why
<string name="txtCredits">Some text here<a href="google.com">Google</a></string> For above snippet Click on Some text here should not work in my case what should i do ?
android:focusable="true" solved my problem

P
Peter Mortensen

Buried in the API demos, I found the solution to my problem:

File Link.java:

    // text2 has links specified by putting <a> tags in the string
    // resource.  By default these links will appear but not
    // respond to user input.  To make them active, you need to
    // call setMovementMethod() on the TextView object.

    TextView t2 = (TextView) findViewById(R.id.text2);
    t2.setMovementMethod(LinkMovementMethod.getInstance());

I removed most of the attributes on my TextView to match what was in the demo.

<TextView
    android:id="@+id/text2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/txtCredits"/>

That solved it. It is pretty difficult to uncover and fix.

Important: Don't forget to remove autoLink="web" if you are calling setMovementMethod().


Maybe it's just me, but why would you ever do this with an EditText?
Turns out only setMovementMethod is needed to achieve the goal.
Just as a commment, i have seen some Samsung Galaxy S3 with OS 4.3 that crash when the "setMovementMethod(LinkMovementMethod.getInstance())" is used, so just take that into account, i had to create a validation before adding it
Same here. Note that if setMovementMethod() is called, it is necessary to remove autolink="web" in the XML file, or else link won't work. Thanks for the comment
Just use the "autoLink" attribute in your xml for eg: android:autoLink = "web"
J
Janusz

I'm using only android:autoLink="web" and it works fine. A click on the link opens the browser and shows the correct page.

One thing I could guess is that some other view is above the link. Something that is transparent fills the whole parent but don't displays anything above the link. In this case the click goes to this view instead of the link.


Added more info above. Could it be the way I am defining the string as <string name="txtCredits"><a href="google.com">Google</a></string>? Looks like this is allowed but it's not working for me.
if you use linkify auto you don't need the a href part. The OS will take the string parse it for urls and converts every url to a clickable link. But this won't result in the word google being linked to google.com. It would display www.google.com as link.
android:autoLink also works great for linkifying phone numbers, addresses, and e-mail addresses (or all of the above).
No it's not, because this answer doesn't work if you wan't to use an anchor tag with a display text different from the URL
Yeah, it works!. You can change the link color using this attribute in xml. android:textColorLink="#03A9F4"
J
Jeshurun

After spending some time with this, I have found that:

android:autoLink="web" works if you have full links in your HTML. The following will be highlighted in blue and clickable:

Some text http://www.google.com Some text http://www.google.com

view.setMovementMethod(LinkMovementMethod.getInstance()); will work with the following (will be highlighted and clickable):

Some text http://www.google.com Some text http://www.google.com Some text Go to Google

Note that the third option has a hyperlink, but the description of the link (the part between the tags) itself is not a link. android:autoLink="web" does NOT work with such links.

android:autoLink="web" if set in XML will override view.setMovementMethod(LinkMovementMethod.getInstance()); (i.e.; links of the third kind will be highlighted, but not clickable).

The moral of the story is use view.setMovementMethod(LinkMovementMethod.getInstance()); in your code and make sure you don't have android:autoLink="web" in your XML layout if you want all links to be clickable.


setMovementMethod doesn't work with second option you mentioned ie google.com.. any update?
Thanks for pointing out that <a href="http://www.google.com">Go to Google</a> won't work for autoLink. For so many answers on SO, this is the only one which mentioned it. Thank you!
P
Peter Mortensen

The above solutions didn't work for me, but the following did (and it seems a bit cleaner). First, in the string resource, define your tag opening chevrons using the HTML entity encoding, i.e.:

&lt;a href="http://www.google.com">Google&lt;/a>

And not:

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

In general, encode all the chevrons in the string like that. BTW, the link must start with http://

Then (as suggested here) set this option on your TextView:

 android:linksClickable="true"

Finally, in code, do:

((TextView) findViewById(R.id.your_text_view)).setMovementMethod(LinkMovementMethod.getInstance());
((TextView) findViewById(R.id.your_text_view)).setText(Html.fromHtml(getResources().getString(R.string.string_with_links)));

That's it. No regular expressiones or other manual hacks are required.


This will create an HTML Parser everytime this code is executed. Be aware of that if you use this to create links inside a list item or at other performance critical places in your app. During creation of a listitem this increases the execution time of my getView Methods off 50%
Also note spaces in the URL must be replaced with %20
You can avoid the entity encoding problems by wrapping your string in the <![CDATA[ ... ]]> tag.
WORKS for me, thank you. Not working with <![CDATA[...]]> tag.
This should be the answer! Worked perfectly well with my native app
P
Peter Mortensen

I simply used this:

Linkify.addLinks(TextView, Linkify.ALL);

It makes the links clickable, given here.


This answer is the best. Works on every Android version and we just need to add that method when the text in set in the TextView. Bonus : it allow us to add customizable links clickable
Really simplest and best answer. it works for email/web at same time.... thanks man!!!
Use LinkifyCompat if you need some of the newer advanced features
Good, it makes urls without <a href... clickable
The link is dead
P
Peter Mortensen

If you want to add an HTML-like link, all you need to do is:

add a resource HTML-like string: Google

add your view to the layout with no link-specific configuration at all: `

add the appropriate MovementMethod programmatically to your TextView: mLink = (TextView) findViewById(R.id.link); if (mLink != null) { mLink.setMovementMethod(LinkMovementMethod.getInstance()); }

That's it! And yes, having options like "autoLink" and "linksClickable" working on explicit links only (not wrapped into HTML tags) is very misleading to me too...


+1 You're right. There should be an option to enter a pattern your self so that this is matched. This way it's pretty dumb.
P
Peter Mortensen

The following should work for anyone who is looking for a combination of text and hyperlink within an Android app.

In string.xml:

<string name="applink">Looking for Digital Visiting card? 
<a href="https://play.google.com/store/apps/details?id=com.themarkwebs.govcard">Get it here</a>
</string>

Now you can utilise this string in any given View like this:

<TextView
    android:id="@+id/getapp"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:gravity="center"
    android:textColor="@color/main_color_grey_600"
    android:textSize="15sp"
    android:text="@string/applink"/>

Now, in your Activity or Fragment, do the following:

TextView getapp =(TextView) findViewById(R.id.getapp);
getapp.setMovementMethod(LinkMovementMethod.getInstance());

By now, you don't require to set android:autoLink="web" or android:linksClickable="true" using this approach.


This works well, but when yo press back from the web opened, only close the browser, but not return to the app.
Important: Don't forget to remove autoLink="web" if you are calling setMovementMethod().
Thanks. It worked perfectly on my project.
4
4 revs, 4 users 88%

I added this line to the TextView: android:autoLink="web"
Below is an example of usage in a layout file.

layout.xml sample

    <TextView
        android:id="@+id/txtLostpassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:autoLink="email"
        android:gravity="center"
        android:padding="20px"
        android:text="@string/lostpassword"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <TextView
        android:id="@+id/txtDefaultpassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:autoLink="web"
        android:gravity="center"
        android:padding="20px"
        android:text="@string/defaultpassword"
        android:textAppearance="?android:attr/textAppearanceSmall" />

string.xml

<string name="lostpassword">If you lost your password please contact <a href="mailto:support@cleverfinger.com.au?Subject=Lost%20Password" target="_top">support@cleverfinger.com.au</a></string>

<string name="defaultpassword">User Guide <a href="http://www.cleverfinger.com.au/user-guide/">http://www.cleverfinger.com.au/user-guide/</a></string>

P
Peter Mortensen

I hope this will help you;

String value = "<html>Visit my blog <a href=\"http://www.maxartists.com\">mysite</a> View <a href=\"sherif-activity://myactivity?author=sherif&nick=king\">myactivity</a> callback</html>";
TextView text = (TextView) findViewById(R.id.text);

text.setText(Html.fromHtml(value));
text.setMovementMethod(LinkMovementMethod.getInstance());

This works great. Also make sure you remove android:autoLink=? from your TextView.
This is what finally worked for me. Valid HTML and not using android:autoLink=? is important!
For Xamarin, the word shows but is not underlined and can't be clicked using the above and NOT these parameters: autoLink, linksClickable
For Xamarin setting those and setting Text or setting TextFormatted also yields the word but its not clickable nor blue/underlined. Removing the autoLink also fails. Removing only linksClickable also fails. Removing both also fails.
helloWorld.TextFormatted = Html.FromHtml (linkURL); with and without those also fails. (not linked, not blue, can't be clicked)
P
Peter Mortensen

The easiest thing that worked for me was to use Linkify

TextView txt_Message = (TextView) view.findViewById(R.id.txt_message);
txt_Message.setText("This is link https://www.google.co.in/");
Linkify.addLinks(txt_Message, Linkify.WEB_URLS);

And it will automatically detect the web URLs from the text in the textview.


True, but they won't be clickable.
The links are clickable.
P
Peter Mortensen

You only need to add this in the text view in XML:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:autoLink="web"/>

R
Reed

Richard, next time, you should add this code under TextView at the layout XML instead.

android:autoLink="all"

This should be like this.

<TextView 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:text="@string/txtCredits"
    android:id="@+id/infoTxtCredits"
    android:autoLink="all"
    android:linksClickable="true">
</TextView>

You don't need to use this code (t2.setMovementMethod(LinkMovementMethod.getInstance());) in order to make the link clickable.

Also, here's the truth: as long as you set the autoLink and the linksClickable, don't forget to add this at String.xml file so that the clickable link will work.

<string name="txtCredits"><a href="http://www.google.com">Google</a></string>

Doesn't work for me. The link is clickable indeed, but the whole string is displayed, not just "Google". In fact, none of the answers here or combination thereof works so far.
Is your device or emulator internet enabled and set it to ON (wifi) or have LAN connected, @Violet Giraffe?
It is. I never managed to make links clickable using just XML attributes, had to resort to Java code for that. Which is no big deal, but not nice.
I'm having the same problem as Violet, sure wish someone figured this out.
P
Peter Mortensen

Manage Linkify text color also

https://i.stack.imgur.com/hCBt1.png

tv_customer_care_no.setLinkTextColor(getResources().getColor(R.color.blue));
tv_customer_care_no.setText("For us to reach out to you, please fill the details below or contact our customer care at 18004190899 or visit our website http://www.dupont.co.in/corporate-links/contact-dupont.html");
Linkify.addLinks(tv_customer_care_no, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS);
Linkify.addLinks(tv_customer_care_no, Linkify.ALL);

P
Peter Mortensen

By using linkify:

Linkify takes a piece of text and a regular expression and turns all of the regex matches in the text into clickable links:

TextView textView = (TextView) findViewById(R.id.textView);
textView.setText("http://example.com");
Linkify.addLinks(textView, Linkify.WEB_URLS);

Don't forget to

import android.widget.TextView;

P
Peter Mortensen

Here is a very one-line Android code to make phone and URL selectable from textView no matter what the string is and what the data is. You don’t need to use any HTML tags for this.

TextView textView = (TextView)findViewById(R.id.textView1);
textView.setText("some URL is www.google.com phone 7504567890 another URL lkgndflg.com ");

// Makes the textView's Phone and URL (hyperlink) select and go.
Linkify.addLinks(textView, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS);

a
aLearner

I noticed that using android:autoLink="web" thus

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content" 
    android:autoLink="web"/>

worked OK for URLs but since I had an e-mail address and phone number that I wanted to link as well, I ended up using this line android:autoLink="all" like this

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:autoLink="all"/>

and it worked like a charm.


P
Peter Mortensen

The accepted answer is correct, but it will mean that phone numbers, maps, email addresses, and regular links, e.g., http://google.com without href tags will no longer be clickable since you can't have an autolink in the XML content.

The only complete solution to have everything clickable that I have found is the following:

Spanned text = Html.fromHtml(myString);
URLSpan[] currentSpans = text.getSpans(0, text.length(), URLSpan.class);
SpannableString buffer = new SpannableString(text);
Linkify.addLinks(buffer, Linkify.ALL);
for (URLSpan span : currentSpans) {
    int end = text.getSpanEnd(span);
    int start = text.getSpanStart(span);
    buffer.setSpan(span, start, end, 0);
}
textView.setText(buffer);
textView.setMovementMethod(LinkMovementMethod.getInstance());

And the TextView should not have android:autolink. There's no need for android:linksClickable="true" either; it's true by default.


for me it worked without this, the accepted answer worked fine @Kelly can you tell the android version and device on which you got the issue?
Doesn't work for myapp:// schemes (for Deep Linking).
The syntax highlighting seems off. E.g. near "text.length()". Is it?
P
Piyush

Be sure to not use setAutoLinkMask(Linkify.ALL) when using setMovementMethod(LinkMovementMethod.getInstance()) and Html.fromHTML() on properly formatted HTML links (for example, <a href="http://www.google.com/">Google</a>).


P
Peter Mortensen

You need only this:

android:autoLink="web"

Insert this line into a TextView that can be clickable with a reference to the web. The URL is set as a text of this TextView.

Example:

 <TextView
    android:id="@+id/textViewWikiURL"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:textStyle="bold"
    android:text="http://www.wikipedia.org/"
    android:autoLink="web" />

P
Peter Mortensen

Use this...

TextView.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        Intent in=new Intent(Intent.ACTION_VIEW,Uri.parse("http://www.twitter.com/"));
                        startActivity(in);
                    }
                    
                });

And add a permission in the manifest file:

<uses-permission android:name="android.permission.INTERNET"/>

This will work, but bear in mind the app may not need Internet permission beyond this clickable TextView. Maybe overkill in those cases
Does it really relate to the question?
This wasn't relevant to the question.
This will never fail!
I like this method as it allows us to have just the anchor text show rather than the full URL. The anchor text can also be styled eg colored green and underlined.
P
Peter Mortensen

This is how I solved clickable and visible links in a TextView (by code)

private void setAsLink(TextView view, String url){
    Pattern pattern = Pattern.compile(url);
    Linkify.addLinks(view, pattern, "http://");
    view.setText(Html.fromHtml("<a href='http://" + url + "'>http://" + url + "</a>"));
}

but I'd like to see the text and when clicking the text it redirect to the link (opened by the browser)? This solution doesn't solve that, does it?
P
Peter Mortensen

Use the below code:

String html = "<a href=\"http://yourdomain.com\">Your Domain Name</a>"
TextView textview = (TextView) findViewById(R.id.your_textview_id);
textview.setMovementMethod(LinkMovementMethod.getInstance());
textview.setText(Html.fromHtml(html));

B
Benny

[Tested in Pre-lollipop as well as in Lollipop and above]

You can get your HTML string from the backend or from your resources files. If you put your text as an resource string, make sure to add the CDATA tag:

<string name="your_text">![CDATA[...<a href="your_link">Link Title</a>  ...]]</string>

Then in code you need to get the string and assign it as HTML and set a link movement method:

String yourText = getString(R.string.your_text);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
   textView.setText(Html.fromHtml(yourText, Html.FROM_HTML_MODE_COMPACT));
} else {
   textView.setText(Html.fromHtml(yourText));
}

try {
   subtext.setMovementMethod(LinkMovementMethod.getInstance());
} catch (Exception e) {
   //This code seems to crash in some Samsung devices.
   //You can handle this edge case base on your needs.
}

P
Peter Mortensen

I had to hunt this down in a couple places, but I finally got this version of the code to work.

File strings.xml:

<string name="name1">&lt;a href="http://www.google.com">link text1&lt;/a></string>
<string name="name2">&lt;a href="http://www.google.com">link text2&lt;/a></string>

File myactivity.xml:

<TextView
    android:id="@+id/textview1"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:layout_marginTop="5dp" />

<TextView
    android:id="@+id/textview2"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:layout_marginTop="5dp" />

File myactivty.java (in onCreate()):

TextView tv1 = (TextView)findViewById(R.id.textview1);
TextView tv2 = (TextView)findViewById(R.id.textview2);

tv1.setText(Html.fromHtml(getResources().getString(R.string.name1)));
tv2.setText(Html.fromHtml(getResources().getString(R.string.name2)));
tv1.setMovementMethod(LinkMovementMethod.getInstance());
tv2.setMovementMethod(LinkMovementMethod.getInstance());

This will create two clickable hyperlinks with the text link text1 and link text2 which redirect the user to Google.


A
Akexorcist

Add CDATA to your string resource

Strings.xml

<string name="txtCredits"><![CDATA[<a href=\"http://www.google.com\">Google</a>]]></string>

P
Peter Mortensen

The reason you're having the problem is that it only tries to match "naked" addresses. Things like "www.google.com" or "http://www.google.com".

Running your text through Html.fromHtml() should do the trick. You have to do it programmatically, but it works.


The links in the TextView are a different color than other text in the string, so I think they're being recognized as links. They're just not clickable :-(
P
Peter Mortensen

If using an XML-based TextView, for your requirement you need to do just two things:

Identify your link in the string, such as "this is my WebPage." You can add it in the XML content or in the code. In the XML content that has the TextView, add these: android:linksClickable="true" android:autoLink="web"


P
Peter Mortensen

I just wasted so much time to figure out you have to use getText(R.string.whatever) instead of getString(R.string.whatever)...

Anyway, here is how I got mine working. With multiple hyperlinks in the same text view too.

TextView termsTextView = (TextView) getActivity().findViewById(R.id.termsTextView);
termsTextView.append("By registering your account, you agree to our ");
termsTextView.append(getText(R.string.terms_of_service));
termsTextView.append(", ");
termsTextView.append(getText(R.string.fees));
termsTextView.append(", and the ");
termsTextView.append(getText(R.string.stripe_connected_account_agreement));

termsTextView.setMovementMethod(LinkMovementMethod.getInstance());

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/termsTextView"/>

String example:

    <string name="stripe_connected_account_agreement"><a href="https://stripe.com/connect/account-terms">Stripe Connected Account Agreement</a></string>

This is so much more straight-forward and easy to use. I have multiple links with custom text working in a dynamically added TextView because of this. This needs the most upvotes possible. Been breaking my head over Spanned strings, custom TextViews and HtmlCompat.fromHtml methods. Thank you so much @luca992.
E
E_net4 - Mr Downvoter

Add this in your edittext:

        android:autoLink="web"
        android:linksClickable="true"

f
farhanjk

Create an extension method on SpannableString:

private fun SpannableString.setLinkSpan(text: String, url: String) {
    val textIndex = this.indexOf(text)
    setSpan(
        object : ClickableSpan() {
            override fun onClick(widget: View) {
                Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url) }.also { startActivity(it) }
            }
        },
        textIndex,
        textIndex + text.length,
        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
    )
}

Use it to make string in your TextView clickable:

    myTextView.apply {
        movementMethod = LinkMovementMethod.getInstance()

        val googleUrl = "http://www.google.com"
        val microsoftUrl = "http://www.microsoft.com"

        val google = "Google"
        val microsoft = "Microsoft"

        val message = SpannableString("$google & $microsoft").apply {
            setLinkSpan(google, googleUrl)
            setLinkSpan(microsoft, microsoftUrl)
        }

        text = message
    }

Enjoy!

https://i.stack.imgur.com/83Wkz.png