Related
I am developing an accessible android application where people would be using Explore by Touch and TalkBack accessibility services to use my application.
This is my Android XML code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/LinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/forename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:layout_marginLeft="15dip"
android:textSize="20sp"
android:text="#string/forenameText"
android:contentDescription="#null"/>
<EditText
android:id="#+id/EditTextForename"
android:layout_width="285dp"
android:layout_height="65dp"
android:layout_marginTop="10dip"
android:layout_marginLeft="15dip"
android:hint="#string/forenameHint"
android:inputType="textPersonName"
android:lines="1"
android:singleLine="true"
android:textSize="20sp" >
</EditText>
</LinearLayout>
strings.xml
<string name="forenameText">Forename</string>
<string name="forenameHint">Enter your forename here</string>
TextView displays the title "Forename" and EditText allows me to enter some details in the form field. The problem I have is that when I
drag my finger across the screen by using Explore by Touch, TalkBack picks up the title of the TextView and announces it aloud as "Forename". I want the TextView to only display text and not provide any audible feedback.
I have set contentDescription to #null as you can see from the code above, but TalkBack still announces "Forename" when my finger is located over the
TextView.
I have also tried setting contentDescription in my Java class:
TextView forename=(TextView)findViewById(R.id.forename);
forename.setContentDescription("");
However, I still get the same problem. Is there any other way to set contentDescription to null/empty and prevent TalkBack from announcing it aloud?
Java code:
public class MainActivity extends Activity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View forename = findViewById(R.id.forename);
forename.setAccessibilityDelegate(new AccessibilityDelegate() {
public boolean performAccessibilityAction (View host, int action, Bundle args){
return true;
}
});
}
}
Since API 16, Android introduced the following:
android:importantForAccessibility="no"
or
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO)
Which allows developers to disable talkback all together for certain views.
http://developer.android.com/reference/android/view/View.html
For better backwards compatibility:
ViewCompat.setImportantForAccessibility(
decorativeTextView,
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);
I was trying to do the same today, and was able to set an 'empty' contentDescription on a TextView like so (using a non-breaking whitespace):
decorativeTextView.setContentDescription("\u00A0");
now TalkBack doesn't say anything for that TextView.
but I agree with Nick about leaving the label as readable in your case, because hint is only read for empty EditTexts.
Why do you not want the TextView to speak "forename"? It is being used as a label for the EditText. Once the user has entered some text the hint "enter your forename here" would no longer be spoken - as far as I know - so the TextView given the user some context for the EditText.
Similarly the announcement of "editbox" gives the user the role of the EditText control. While "form field" might be better it would not be the same behavior as in other apps and in the OS.
I had a similar problem. I eventually solved it by using the setAccessibilityDelegate method and overriding View.AccessibilityDelegate's performAccessibilityAction method.
try this:
View forename = findViewById(R.id.forename);
forename.setAccessibilityDelegate(new AccessibilityDelegate() {
public boolean performAccessibilityAction (View host, int action, Bundle args){
return true;
}
});
I had the same problem, and the only thing that worked for me was android:contentDescription=" " (white space).
I am using the TextInputLayout to implement the floating label pattern. However, when I set the text programmatically on the EditText, I still get the animation of the label moving from the control to the label - the same as if the user had clicked it.
I don't want this animation though if I set it programmatically, is this possible? Here is my code:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/root">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText1" />
</android.support.design.widget.TextInputLayout>
And in the onResume I do:
TextInputLayout root = (TextInputLayout)findViewById(R.id.root);
EditText et = (EditText)root.findViewById(R.id.editText1);
et.setText("Actual text");
root.setHint("Hint");
As of v23 of the support libs, a setHintAnimationEnabled method has been added. Here are the docs. So you can set this new attribute to false in the XML and then programmatically set it to true after you've finished populating the editText. OR simply handle it all programmatically, as needed.
So in your example, that would become something like:
TextInputLayout root = (TextInputLayout)findViewById(R.id.root);
root.setHintAnimationEnabled(false);
root.setHint("Hint");
EditText et = (EditText)root.findViewById(R.id.editText1);
et.setText("Actual text");
// later...
root.setHintAnimationEnabled(true);
Of course, be sure to open your Android SDK Manager and update your Android Support Library to rev. 23 and Android Support Repository to rev. 17 first and then add that to build.gradle via:
compile 'com.android.support:design:23.0.0'
Note that as the Design library depends on the Support v4 and AppCompat Support Libraries, those will be included automatically when you add the Design library dependency.
Put this attribute app:hintEnabled="false" here:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintEnabled="false">
It works for me
I have found an (unwieldy) way to do that. Looking into the source code of the TextInputLayout, I've discovered that the only occasion when the class doesn't update it's hint with animation is when the EditText is added to it. The only obstacle is that you can only add it once to the layout, once it is there, it will permanently be tied to it, and there's no way to remove it.
So here's the solution:
Create a TextInputLayout without the EditText. Programmatically or via XML inflation - doesn't matter, but it has to be empty.
Create the EditText and set its text to whatever you need.
Add the EditText to the TextInputLayout.
Here's an example:
TextInputLayout hintView = (TextInputLayout) findViewById(R.id.hint_view);
hintView.setHint(R.string.hint);
EditText fieldView = new EditText(hintView.getContext());
fieldView.setText(value);
hintView.addView(fieldView);
Unfortunately, if you want to set the text to something else without the animation, you will have to repeat all these steps, except for the creation of a new EditText (the last one can be reused). I hope Google can fix this, because it is really inconvenient, but for now that's what we have.
Update: this is, thankfully, fixed in the design library 23.0.0, so just update to that version, and you won't have to do all this crazy stuff.
You can disable it by using
app:hintAnimationEnabled="false"
I will give you simple code and you don't have to make all programmatically just add xlm attribute and that's all.
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintAnimationEnabled="true"
app:passwordToggleEnabled="true">
<EditText
android:id="#+id/password_field_activity_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:hint="#string/password"
android:inputType="textPassword"
android:padding="10dp"
android:textColor="#color/color_holo_light_gray"
android:textColorHint="#color/color_holo_light_gray"
android:textCursorDrawable="#drawable/cursor_drawable" />
</android.support.design.widget.TextInputLayout>
Hope it will help
I wrote a small method to run after loading the view hierarchy that disables animation on initial display but enables it after wards. Add this to your Base Activity/Fragment/View and it will solve it issue.
private void setTextInputLayoutAnimation(View view) {
if (view instanceof TextInputLayout) {
TextInputLayout til = (TextInputLayout) view;
til.setHintAnimationEnabled(false);
til.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override public boolean onPreDraw() {
til.getViewTreeObserver().removeOnPreDrawListener(this);
til.setHintAnimationEnabled(true);
return false;
}
});
return;
}
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
setTextInputLayoutAnimation(child);
}
}
}
I check out ideas about support library v23 - it's does not work yet :( Programmatically inserting of EditText is unusable if you wish to use databinding labrary
In result of research I found solution without full disabling of animation:
layout.xml
<android.support.design.widget.TextInputLayout
android:id="#+id/text_til"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/product_title_placeholder">
<android.support.design.widget.TextInputEditText
android:id="#+id/text_tiet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#={bindingText}"/>
</android.support.design.widget.TextInputLayout>
Activity.java
final TextInputLayout textLayout = (TextInputLayout) findViewById(R.id.text_til);
if(binding.getText() != null) {
// disable animation
textLayout.setHintAnimationEnabled(false);
final TextInputEditText editText = (TextInputEditText) titleLayout.findViewById(R.id.text_tiet);
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
// enable animation after layout inflated
textLayout.setHintAnimationEnabled(true);
editText.setOnFocusChangeListener(null);
}
});
}
// manage focus for new binding object
((View)textLayout .getParent()).setFocusableInTouchMode(binding.getText() == null);
It's looks not prettily, but it works :)
I am taking reference from TextJustify-Android. I am implementing option 2 in above link. When I run my app on emulator text appears one word in one line, next word in next line and so on. I dont know whats wrong in my code. Please help me. Thanks.
Activity class code-
textView1 = (TextView) findViewById (R.id.textView1);
textView1.setMovementMethod(new ScrollingMovementMethod());
textView1.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener()
{
boolean isJustified = false;
#Override
public boolean onPreDraw()
{
if(!isJustified)
{
TextJustifyUtils.run(textView1,0);
isJustified = true;
}
return true;
}
});
Xml code-
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="8"
android:gravity="center">
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"
android:text="#string/his"
android:textColor="#FFFFFF"/>
</LinearLayout>
And I am implementing TextJustifyUtils class in my app as suggested in above link.
I have made one change In that link given TextJustifyUtils.run(textView1); and In my code eclipse suggest me to change in TextJustifyUtils.run(textView1,0);. Is anything wrong with this?
Update:
In TextJustifyUtils I change public static void justify(TextView textView) into public static void run(TextView textView) as commented by the author there and TextJustifyUtils.run(textView1,0); into TextJustifyUtils.run(textView1); in Activity class. But the output is same as I type in my textView i.e text without justification.
If some one following the above link to justify text please choose option 1. Its work fine. And if you have any problem. Ask from author. I think he always happy to help you nice guy. As he helps me so much. And option 1 working with minor changes.
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"/>
where #string/txtCredits is a string resource that contains Link text.
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">Google</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.
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().
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.
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.
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.:
<a href="http://www.google.com">Google</a>
And not:
Google
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.
I simply used this:
Linkify.addLinks(TextView, Linkify.ALL);
It makes the links clickable, given here.
If you want to add an HTML-like link, all you need to do is:
add a resource HTML-like string:
<string name="link">Google</string>
add your view to the layout with no link-specific configuration at all:
<TextView
android:id="#+id/link"
android:text="#string/link" />`
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...
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?
Get it here
</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.
I added this line to the TextView: android:autoLink="web"
Below is an example of usage in a layout file.
layout.xml
<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 support#cleverfinger.com.au</string>
<string name="defaultpassword">User Guide http://www.cleverfinger.com.au/user-guide/</string>
I hope this will help you;
String value = "<html>Visit my blog mysite View myactivity callback</html>";
TextView text = (TextView) findViewById(R.id.text);
text.setText(Html.fromHtml(value));
text.setMovementMethod(LinkMovementMethod.getInstance());
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.
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"/>
Manage Linkify text color also
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);
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;
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">Google</string>
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);
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.
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.
Be sure to not use setAutoLinkMask(Linkify.ALL) when using setMovementMethod(LinkMovementMethod.getInstance()) and Html.fromHTML() on properly formatted HTML links (for example, Google).
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" />
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"/>
Add this to your EditText:
android:autoLink="web"
android:linksClickable="true"
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>"));
}
Use the below code:
String html = "Your Domain Name"
TextView textview = (TextView) findViewById(R.id.your_textview_id);
textview.setMovementMethod(LinkMovementMethod.getInstance());
textview.setText(Html.fromHtml(html));
[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[...Link Title ...]]</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.
}
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!
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"><a href="http://www.google.com">link text1</a></string>
<string name="name2"><a href="http://www.google.com">link text2</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.
Add CDATA to your string resource
Strings.xml
<string name="txtCredits"><![CDATA[Google]]></string>
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.
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"
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">Stripe Connected Account Agreement</string>
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"/>
where #string/txtCredits is a string resource that contains Link text.
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">Google</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.
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().
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.
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.
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.:
<a href="http://www.google.com">Google</a>
And not:
Google
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.
I simply used this:
Linkify.addLinks(TextView, Linkify.ALL);
It makes the links clickable, given here.
If you want to add an HTML-like link, all you need to do is:
add a resource HTML-like string:
<string name="link">Google</string>
add your view to the layout with no link-specific configuration at all:
<TextView
android:id="#+id/link"
android:text="#string/link" />`
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...
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?
Get it here
</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.
I added this line to the TextView: android:autoLink="web"
Below is an example of usage in a layout file.
layout.xml
<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 support#cleverfinger.com.au</string>
<string name="defaultpassword">User Guide http://www.cleverfinger.com.au/user-guide/</string>
I hope this will help you;
String value = "<html>Visit my blog mysite View myactivity callback</html>";
TextView text = (TextView) findViewById(R.id.text);
text.setText(Html.fromHtml(value));
text.setMovementMethod(LinkMovementMethod.getInstance());
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.
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"/>
Manage Linkify text color also
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);
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;
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">Google</string>
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);
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.
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.
Be sure to not use setAutoLinkMask(Linkify.ALL) when using setMovementMethod(LinkMovementMethod.getInstance()) and Html.fromHTML() on properly formatted HTML links (for example, Google).
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" />
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"/>
Add this to your EditText:
android:autoLink="web"
android:linksClickable="true"
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>"));
}
Use the below code:
String html = "Your Domain Name"
TextView textview = (TextView) findViewById(R.id.your_textview_id);
textview.setMovementMethod(LinkMovementMethod.getInstance());
textview.setText(Html.fromHtml(html));
[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[...Link Title ...]]</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.
}
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!
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"><a href="http://www.google.com">link text1</a></string>
<string name="name2"><a href="http://www.google.com">link text2</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.
Add CDATA to your string resource
Strings.xml
<string name="txtCredits"><![CDATA[Google]]></string>
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.
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"
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">Stripe Connected Account Agreement</string>