Dynamically replace url's with custom text hyperlink url in Android TextView - android

Let’s say you have the string:
"https://google.com to go to google. https://amazon.com to go to Amazon."
In a TextView, how would you replace the url’s with a link that shows “Click here” (or “Haz clic aquí” in spanish) and would take you to the correct url?
Keep in mind that the text is dynamic, it’s retrieved from the API, and there is no way to know if or how many links may be in any given post.
The finished product should look like this:
“Click here to go to google. Click here to go to Amazon.”

After many many hours…
Here is my solution.
I put this code inside the RecyclerView adapter's onBindViewHolder().
// replace url links with clickable link that says "Click here" (or "Haz clic aquí" in Spanish).
// link color is set in TextView in the xml.
// SpannableStringBuilder is mutable, so we can replace the link.
SpannableStringBuilder spannableStringBuilder = new
SpannableStringBuilder(newsFeedItem.getBody());
// use Linkify to automatically set all Url's in the string.
Linkify.addLinks(spannableStringBuilder,Linkify.WEB_URLS);
//do this process for each Url
for (URLSpan urlSpan: spannableStringBuilder.getSpans(0,spannableStringBuilder.length(),URLSpan.class)){
int start = spannableStringBuilder.getSpanStart(urlSpan);
int end = spannableStringBuilder.getSpanEnd(urlSpan);
// put whatever you want it to say into the next line where I wrote "Click here".
SpannableString customLinkSpannableString = new SpannableString("Click here");
customLinkSpannableString.setSpan(urlSpan,0, customLinkSpannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableStringBuilder.replace(start, end, customLinkSpannableString);
}
// now set the fixed up string into the TextView and set LinkMovementMethod.
textView.setText(spannableStringBuilder);
textView.setMovementMethod(LinkMovementMethod.getInstance());

Related

How to make a string clickable in Android [duplicate]

This question already has answers here:
How to make normal links in TextView clickable?
(5 answers)
Closed 6 years ago.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="legalText">
By using this xxxxxxxxxxx app, I agree to the Terms of Use and Notice of Privacy Policy [[need official name]] in this app. I understand that use of this xxxxxxxxx app is at my own risk and discretion. I understand and agree that the health information I give to xxxxxxx in this app is truthful and will be the only source of health information used by the xxxxxxxxxx providers during the course of my evaluation and treatment through xxxxxxxxxx. Also, as part of my use of the xxxxxxxx app, I agree that I will not use this app for any purpose that is prohibited by the xxxxxxxx Terms of Use [[link to Terms]] and Consent to Telehealth [[Link to Consent to Telehealth]]”, and Consent to Request Medical Services [insert link to Consent to Request Medical Services].
</string>
</resources>
I need to put links to other xml pages and html pages at bracket locations in this xml file. How do I do that?
Here's what you can do:
Break that one string into several string resources (atleast separate the app-name and links to a different string resource.
Contruct the full legalText by joining the substrings found in step 1. Use the <a href= "link"><a/> tag for the substrings with link. You can style the rest of the substrings accordingly, as you get the idea.
Use the Html.fromHtml method to show the formatting:
Spannable text = (Spannable)Html.fromHtml(legalText);
//this one here to get the links clickable:
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(text);
You might need to get rid of extra underlines at this point, therefore use this method:
private void stripUnderlines(TextView textView) {
Spannable s = (Spannable)textView.getText();
URLSpan[] spans = s.getSpans(0, s.length(), URLSpan.class);
for (URLSpan span: spans) {
int start = s.getSpanStart(span);
int end = s.getSpanEnd(span);
s.removeSpan(span);
span = new URLSpanNoUnderline(span.getURL());
s.setSpan(span, start, end, 0);
}
textView.setText(s);
}
As far as i know, it is not possible to add links directly into strings, but you can create different strings and assemble your text with different TextViews and set OnClickListeners and a link-style to the TextViews you want to add link.
If you develop in java and Android Studio, you only have to set an onClickListener on the TextView the same way you do for a button.
You should also add styles such as underline or Color to let the user know there is a link.

AutoLink with hyperLink android

I have a textview which can contain links like https://www.google.com and hyper links with anchor tag Google
Now, I have added the below properties on this textview.
Linkify.addLinks(textview, Linkify.WEB_URLS);
textview.setMovementMethod(LinkMovementMethod.getInstance());
But the links like https://www.google.com these are coming fine in blue and redirecting to the page but anchor tags are not coming in blue and they are not redirecting it.
So, I want to make my textview to render both type of links: direct links and hyper links. How can I do this.
Linkify (the way you've invoked it) only knows to convert things that actually look like web URLs (i.e. they begin with http or https, followed by colon and two slashes, etc. etc).
If you want to convert something else into links, you will have to add some more parameters to Linkify to give it more smarts to convert what you want. You can create a MatchFilter and a TransformFilter then call Linkify.addLinks(TextView text, Pattern p, String scheme, Linkify.MatchFilter matchFilter, Linkify.TransformFilter transformFilter)
But it looks to me like you want to take a word like "Google" and add a link for "https://www.google.com". That's not something that can be scanned. For that, you need to use a SpannableStringBuilder. Your code might look something like this:
String text = "This is a line with Google in it.";
Spannable spannable = new SpannableString(text);
int start = text.indexOf("Google");
int end = start + "Google".length();
URLSpan urlSpan = new URLSpan("https://www.google.com");
spannable.setSpan(urlSpan, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(spannable);
It's mentioned in javadoc of Linkify#addLinks(Spannable, Int) that:
...If the mask is nonzero, it also removes any existing URLSpans attached to the Spannable, to avoid problems if you call it repeatedly on the same text.
Although it is not mentioned in Linkify#addLinks(TextView, Int) which you're using, it appears that they follow the same behavior and existing links (i.e. the 'anchor tags' in your question) would be removed before linkify.
To workaround and preserve existing links ('anchor tags' in your case), you need to backup existing spans (i.e. TextView#getText --> convert to Spanned --> use Spanned#getSpans to list existing links --> use Spanned#getSpanStart and Spanned#getSpanEnd and Spanned#getSpanFlags to retrieve the settings of each)
After linkify, re-add the spans (i.e. TextView#getText --> convert to Spannable --> use Spannable#setSpan to re-add the links --> Set the Spannable back with TextView#setText)
Depending on your case, you might also need to check for overlapping 'anchor tags' and 'linkify links' and adjust accordingly...
As you see, this is quite tedious and complex and error prone to code. To simplify things, I have just incorporate all these into Textoo library for reuse and sharing. With Textoo, you can achieve the same by:
TextView myTextView = Textoo
.config((TextView) findViewById(R.id.view_location_disabled))
.linkifyWebUrls()
.apply();
Textoo will preserve exiting links and linkify all non-overlapping web urls.
//the string to add links to
val htmlString = "This has anchors and urls http://google.com also Google."
//Initial span from HtmlCompat will link anchor tags
val htmlSpan = HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_LEGACY) as Spannable
//save anchor links for later
val anchorTagSpans = htmlSpan.getSpans(0, htmlSpan.length, URLSpan::class.java)
//add first span to TextView
textView.text = htmlSpan
//Linkify will now make urls clickable but overwrite our anchor links
Linkify.addLinks(textView, Linkify.ALL)
textView.movementMethod = LinkMovementMethod.getInstance()
textView.linksClickable = true
//we will add back the anchor links here
val restoreAnchorsSpan = SpannableString(textView.text)
for (span in anchorTagSpans) {
restoreAnchorsSpan.setSpan(span, htmlSpan.getSpanStart(span), htmlSpan.getSpanEnd(span), Spanned.SPAN_INCLUSIVE_INCLUSIVE)
}
//all done, set it to the textView
textView.text = restoreAnchorsSpan

Hide only part of text in TextView

Good Day i want to hide some specified or certain part of text in textview!Important: Im not talking about hide the full textview with TextView.setVisibility(View.Gone) I'm not talking about transparent of TEXT in textview!im not talking about hiding full text in textview!So please help me to hide some text.
Example: lets say i have a textview with this text (10-Sporting Goods)
I want to hide the (10-) and show only Sporting Goods text.Any help will be appreciated!Thank you very much beforehand!
Although even i would appreciate for your case to strongly go with DroidWorm/Gabriella approach , just for the information of all the other folks who may see this in future.
If you really wish to hide just a portion of your textview which has the entire string in itself, you should use a SpannableString , as below:-
tvHello = (TextView) findViewById(R.id.tvHello);
SpannableString customText = new SpannableString("10-Sporting Good");
customText.setSpan(new RelativeSizeSpan(.1f), 0, 3, 0);
tvHello.setText(customText);
This code will technically HIDE the 10- from 10-Sporting Good without using a substring.
You could try to get the whole text like
String text = textView.getText().toString();
and then make substring of it like this:
String wantedSubstr = text.substring(4); //for example - everything from the 4th index to the end
then set this substring as text of your textView like this:
textView.setText(wantedSubstr);
There is one the possible solution of it is that..First you have to find the index(position) of "-" and than split the string according to it therefore use below code
String text = textView.getText().toString();
int position=text.indexOf('-');
String wantedSubstr = text.substring(position+1);
textView.setText(wantedSubstr);
Will there always been "10_" in front of it? Or will there always be 3 characters before the text you want? Or will there always be a "-" or "_" before the text you want?
If so, you could just do a simple method which takes the substring and then updates the textview. If so I can help you write a simple method
You cannot hide part of textView, instead you can make a substring of the specific string and setText using it.
Do it like:
String originalString = "10-Sporting Goods";
String subString = originalString.substring(3);
textView.setText(asubstring);

how to add text with format into edit text?

The image is from an app called kakao story.
Suppose there's a post with a list of comments like any sns apps.
When you click a comment, it inserts the user name of the commenter in the edit-text to indicate my new comment is a reply to the user.
(You can't add the same name more than once.)
When you hit backspace to delete the name, the entire characters that make up the name(e.g., chabeau in the example) will be deleted by 1-backspace.
I'm trying to mimic the behavior and want some pointers how to implement it or what to search for.
If you are in search of bubble view. You can achieve it by creating a subclass of android.text.style.DynamicDrawableSpan.ImageSpan which will convert a portion of EditText string into formatted span.
This SO Question will give you some basic idea about creating formatted span.
This is a good tutorial for customizing editext with spans.
And for deleting whole word at once, you can use SPAN_EXCLUSIVE_EXCLUSIVE property.
Below code will format the first four character of the string, Hope this will give you some hint.
final SpannableStringBuilder sb = new SpannableStringBuilder("your text here");
final ForegroundColorSpan fcs
= new ForegroundColorSpan(Color.rgb(158, 158, 158));
// Span to set text color to some RGB value
sb.setSpan(fcs, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
yourTextView.setText(sb);
EditText et = (EditText) findViewById(R.id.edit1);
et.setTextColor(Color.parseColor("yourColorCodeHere"));

How to process textview for HTML and Linkify

I am trying to get a textview to process a hyperlink as well as phone numbers. Say my text is:
"555-555-555, www.google.com, Google!"
If I run Html.fromHtml() on this string, then the TextView shows Google! correctly as a clickable link but not the other two.
If I run Linkify.addLinks(TextView, Linkify.All) on the TextView, then the first two are correctly recognized as a phone number and url, but the html is not processed in the last one.
If I run both of them, then either one or the other is honored, but not both at the same time. (Html.fromHtml will remove the html tags there, but it won't be a link if linkify is called after)
Any ideas on how to get both of these functions to work simultaneously? So all the links are processed correctly? Thanks!
Edit: Also, the text is changed dynamically so I'm not sure how I would be able to go about setting up a Linkify pattern for that.
It's because Html.fromHtml and Linkify.addLinks removes previous spans before processing the text.
Use this code to get it work:
public static Spannable linkifyHtml(String html, int linkifyMask) {
Spanned text = Html.fromHtml(html);
URLSpan[] currentSpans = text.getSpans(0, text.length(), URLSpan.class);
SpannableString buffer = new SpannableString(text);
Linkify.addLinks(buffer, linkifyMask);
for (URLSpan span : currentSpans) {
int end = text.getSpanEnd(span);
int start = text.getSpanStart(span);
buffer.setSpan(span, start, end, 0);
}
return buffer;
}
try to set movement method on your textview instead of using Linkify:
textView.setMovementMethod(LinkMovementMethod.getInstance());
In your TextView's xml layout, you should add the following:
android:autoLink="all"
android:linksClickable="true"
Then you should remove your Linkify code in Java.
It works somehow, but I dont know why. I added a question to see if someone can explain the behavior: Using Linkify.addLinks combine with Html.fromHtml

Categories

Resources