i came into this wired situation, my code is as follow
LinearLayout ll = new LinearLayout(this);
TextView tv = new TextView(this);
ll.addView(tv);
tv.setText(Html.fromHtml("<a STYLE=\"text-decoration:none;\" href=\""
+ StringEscapeUtils.escapeJava(elem.getChildText("newsLink")) + "\">"
+ StringEscapeUtils.escapeJava(elem.getChildText("Title")) + "</a>"));
tv.setTextColor(Color.BLACK);
but the style="text-decoration:none" and tv.setTextColor(color.black)both not working, the link is still in blue with underscore, any hints on why they're not working? Thanks!
you can try this. such as
String content = "your <a href='http://some.url'>html</a> content";
Here is a concise way to remove underlines from hyperlinks:
Spannable s = (Spannable) Html.fromHtml(content);
for (URLSpan u: s.getSpans(0, s.length(), URLSpan.class)) {
s.setSpan(new UnderlineSpan() {
public void updateDrawState(TextPaint tp) {
tp.setUnderlineText(false);
}
}, s.getSpanStart(u), s.getSpanEnd(u), 0);
}
tv.setText(s);
You can use Spannable and URLSpan here to remove hyperlink underline from your code
First of all make your anchor tag text into Spannable
Spannable spannedText = Spannable.Factory.getInstance().newSpannable(
Html.fromHtml(webLinkText));
Create new class URLSpanNoUnderline and extend it with URLSpan and override updateDrawState method. in that method you can set setUnderlineText to false
then use this method you can remove your link
public static Spannable removeUnderlines(Spannable p_Text) {
URLSpan[] spans = p_Text.getSpans(0, p_Text.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = p_Text.getSpanStart(span);
int end = p_Text.getSpanEnd(span);
p_Text.removeSpan(span);
span = new URLSpanNoUnderline(span.getURL());
p_Text.setSpan(span, start, end, 0);
}
return p_Text;
}
For more information you can visit this link
Related
I have a textview with autoLinks set to all. I want to skip numbers like "2018"
which are years, these numbers should not be highlighted. Is there a delimiter I can use in the text so that it skips those numbers while parsing?
Edit:
This issue happens only in Mi devices.
try this....
String s1="jan 2018,Saturday";
String replaceString=s1.replace("2018","");//replaces all occurrences of "2018" to ""
System.out.println(replaceString);
Output := jan ,Saturday.
Use Spanable String in this case to highlight Specific String.
Here is an example:
SpannableString spannableStr = new SpannableString(originalText);
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
spannableStr.setSpan(foregroundColorSpan, 15, 30, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableTextView.setText(spannableStr);
Set color and starting string index and ending index.
For more detail check this link click this link
I searched for your answer try this
private void stripUnderlines(TextView textView) {
Spannable s = new SpannableString(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);
}
This requires a customized version of URLSpan which doesn't enable the TextPaint's "underline" property:
private class URLSpanNoUnderline extends URLSpan {
public URLSpanNoUnderline(String url) {
super(url);
}
#Override public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
}
here is the link
Try This Code :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
highlightTv();
}
protected void highlightTv(){
// Specify the text/word to highlight inside TextView
String textToHighlight = "2018";
// Construct the formatted text
String replacedWith = "<font color='green'>" + textToHighlight + "</font>";
// Get the text from TextView
String originalString = textView.getText().toString();
// Replace the specified text/word with formatted text/word
String modifiedString = originalString.replaceAll(textToHighlight,replacedWith);
// Update the TextView text
mTextView.setText(Html.fromHtml(modifiedString));
}
I tried URLSpan in scannable string like this
private void setSmsText() {
SpannableString string = new SpannableString("Text with a url span");
string.setSpan(new URLSpan("http://www.developer.android.com"), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sms_text.setText(string);
sms_text.setMovementMethod(LinkMovementMethod.getInstance());
}
Here while commenting the setMovementMethod line the text appears to be clickable(url format)
but when uncommenting the text is not clickable
I am not able to navigate to the url by clicking on the text
Try this
SpannableString spannableString = new SpannableString(YOUR_TEXT);
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View widget) {
//your code like open webview or any other
}
};
spannableString.setSpan(clickableSpan, YOUR_TEXT_STARTING_INDEX,YOUR_TEXT_END_INDEX , Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
let me know if this work or not
I am looking to change the text of a TextView view via the .setText("") method while also coloring a part of the text (or making it bold, italic, transparent, etc.)and not the rest. For example:
title.setText("Your big island <b>ADVENTURE!</b>";
I know the above code is incorrect but it helps illustrate what I would like to achieve. How would I do this?
Use spans.
Example:
final SpannableStringBuilder sb = new SpannableStringBuilder("your text here");
// Span to set text color to some RGB value
final ForegroundColorSpan fcs = new ForegroundColorSpan(Color.rgb(158, 158, 158));
// Span to make text bold
final StyleSpan bss = new StyleSpan(android.graphics.Typeface.BOLD);
// Set the text color for first 4 characters
sb.setSpan(fcs, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// make them also bold
sb.setSpan(bss, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
yourTextView.setText(sb);
title.setText(Html.fromHtml("Your big island <b>ADVENTURE!</b>"));
I hope this helps you (it works with multi language).
<string name="test_string" ><![CDATA[<font color="%1$s"><b>Test/b></font>]]> String</string>
And on your java code, you can do:
int color = context.getResources().getColor(android.R.color.holo_blue_light);
String string = context.getString(R.string.test_string, color);
textView.setText(Html.fromHtml(string));
This way, only the "Test" part will be colored (and bold).
If you are using Kotlin you can do the following using the android-ktx library
val title = SpannableStringBuilder()
.append("Your big island ")
.bold { append("ADVENTURE") }
titleTextField.text = title
The bold is an extension function on SpannableStringBuilder. You can see the documentation here for a list of operations you can use.
Another example:
val ssb = SpannableStringBuilder()
.color(green) { append("Green text ") }
.append("Normal text ")
.scale(0.5F) { append("Text at half size ") }
.backgroundColor(green) { append("Background green") }
Where green is a resolved RGB color.
It is even possible to nest spans so you end up with something like an embedded DSL:
bold { underline { italic { append("Bold and underlined") } } }
You will need the following in your app module level build.gradle for it to work:
repositories {
google()
}
dependencies {
implementation 'androidx.core:core-ktx:0.3'
}
Here's an example that will look for all occurrences of a word (case insensitive), and color them red:
String notes = "aaa AAA xAaax abc aaA xxx";
SpannableStringBuilder sb = new SpannableStringBuilder(notes);
Pattern p = Pattern.compile("aaa", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(notes);
while (m.find()){
//String word = m.group();
//String word1 = notes.substring(m.start(), m.end());
sb.setSpan(new ForegroundColorSpan(Color.rgb(255, 0, 0)), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
}
editText.setText(sb);
You can use a Spannable to give certain parts of a text certain aspects. I can look up an example if you want.
Ah, from right here on stackoverflow.
TextView TV = (TextView)findViewById(R.id.mytextview01);
Spannable WordtoSpan = new SpannableString("I know just how to whisper, And I know just how to cry,I know just where to find the answers");
WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 30, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TV.setText(WordtoSpan);
If you want to use HTML, you need to use TextView.setText(Html.fromHtml(String htmlString))
If you want to do that often / repeatedly, you may have a look at a class (SpannableBuilder) I wrote, as Html.fromHtml() is not very efficient (it is using a big xml parsing machinery inside). It is described in this blog posting.
String str1 = "If I forget my promise to ";
String penalty = "Eat breakfast every morning,";
String str2 = " then I ";
String promise = "lose my favorite toy";
String strb = "<u><b><font color='#081137'>"+ penalty +",</font></b></u>";
String strc = "<u><b><font color='#081137'>"+ promise + "</font></b></u>";
String strd = str1 +strb+ str2 + strc;
tv_notification.setText(Html.fromHtml(strd));
or use this code:
SpannableStringBuilder builder = new SpannableStringBuilder();
SpannableString text1 = new SpannableString(str1);
text1.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.silver)), 0, str1.length() - 1, 0);
builder.append(text1);
SpannableString text2 = new SpannableString(penalty);
text2.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.midnight)), 0, penalty.length(), 0);
text2.setSpan(new UnderlineSpan(), 0, penalty.length(), 0);
builder.append(text2);
SpannableString text3 = new SpannableString(str2);
text3.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.silver)),0, str2.length(), 0);
builder.append(text3);
SpannableString text4 = new SpannableString(promise);
text4.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.midnight)), 0, promise.length(), 0);
text4.setSpan(new UnderlineSpan(),0, promise.length(), 0);
builder.append(text4);
tv_notification.setText(builder);
I like to use SpannableStringBuilder by appending the different spans one by one, rather than calling setSpan by calculating the string lengths
as: (Kotlin code)
val amountSpannableString = SpannableString("₹$amount").apply {
// text color
setSpan(ForegroundColorSpan("#FD0025".parseColor()), 0, length, 0)
// text size
setSpan(AbsoluteSizeSpan(AMOUNT_SIZE_IN_SP.spToPx(context)), 0, length, 0)
// font medium
setSpan(TypefaceSpan(context.getString(R.string.font_roboto_medium)), 0, length, 0)
}
val spannable: Spannable = SpannableStringBuilder().apply {
// append the different spans one by one
// rather than calling setSpan by calculating the string lengths
append(TEXT_BEFORE_AMOUNT)
append(amountSpannableString)
append(TEXT_AFTER_AMOUNT)
}
public static void setColorForPath(Spannable spannable, String[] paths, int color) {
for (int i = 0; i < paths.length; i++) {
int indexOfPath = spannable.toString().indexOf(paths[i]);
if (indexOfPath == -1) {
continue;
}
spannable.setSpan(new ForegroundColorSpan(color), indexOfPath,
indexOfPath + paths[i].length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
Using
Spannable spannable = new SpannableString("Your big island ADVENTURE");
Utils.setColorForPath(spannable, new String[] { "big", "ADVENTURE" }, Color.BLUE);
textView.setText(spannable);
You can concatenate two or more Spans. This way is easier to color dynamic text using length value.
SpannableStringBuilder span1 = new SpannableStringBuilder("Android");
ForegroundColorSpan color1=new ForegroundColorSpan(getResources().getColor(R.color.colorPrimary));
span1.setSpan(color1, 0, span1.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
SpannableStringBuilder span2 = new SpannableStringBuilder("Love");
ForegroundColorSpan color2=new ForegroundColorSpan(getResources().getColor(R.color.colorSecondary));
span2.setSpan(color2, 0, span2.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
Spanned concatenated=(Spanned) TextUtils.concat(span1," => ",span2);
SpannableStringBuilder result = new SpannableStringBuilder(concatenated);
TextView tv = (TextView) rootView.findViewById(R.id.my_texview);
tv.setText(result, TextView.BufferType.SPANNABLE);
Use this code its helpful
TextView txtTest = (TextView) findViewById(R.id.txtTest);
txtTest.setText(Html.fromHtml("This is <font color="#ff4343">Red</font> Color!"));
You can use extension function in Kotlin
fun CharSequence.colorizeText(
textPartToColorize: CharSequence,
#ColorInt color: Int
): CharSequence = SpannableString(this).apply {
val startIndexOfText = this.indexOf(textPartToColorize.toString())
setSpan(ForegroundColorSpan(color), startIndexOfText, startIndexOfText.plus(textPartToColorize.length), 0)
}
Usage:
val colorizedText = "this text will be colorized"
val myTextToColorize = "some text, $colorizedText continue normal text".colorizeText(colorizedText,ContextCompat.getColor(context, R.color.someColor))
Html.fromHtml is deprecated
Use HtmlCompat instead
HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY)
If you do not want to get in trouble on lower SDK version use SpannableStringBuilder with ForegroundColorSpan or BackgroundColorSpan as HtmlCompat.fromHtml color style does not applied on older Android version.
I want to show the spanString in Bold style and rest of the string in normal style in TextView. But the whole TextView showed in normal style only. Please help me.
if ((mStoreListValue.get(pos).getStoreStatus().equals("CLOSED"))){
final Dialog dialog = new Dialog(v.getRootView().getContext(), android.R.style.Theme_Translucent_NoTitleBar);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setContentView(R.layout.resclosed_dialog);
ImageView btn_close = dialog.findViewById(R.id.close_btn);
TextView txt_close = dialog.findViewById(R.id.tv_closed);
SpannableString spanString = new SpannableString(sname);
spanString.setSpan(new StyleSpan(Typeface.BOLD), 0, spanString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
txt_close.setText(spanString + " " + mContext.getResources().getString(R.string.closed));
btn_close.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialog.show();
Thats because you just concat SpannableString with String which will be result as toString()(a Normal String with hash code of object). Use a single String with multiple Span.
See the following example.
String s1="My app";
String s2= "Close";
SpannableString spanString = new SpannableString(s1+s2);
spanString.setSpan(new StyleSpan(Typeface.BOLD), 0, s1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spanString.setSpan(new StyleSpan(Typeface.NORMAL), s1.length(), (s1+s2).length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spanString);
Use this
SpannableStringBuilder builder = new SpannableStringBuilder();
SpannableString spanString = new SpannableString(sname);
spanString.setSpan(new StyleSpan(Typeface.BOLD), 0, spanString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append(spanString);
builder.append(mContext.getResources().getString(R.string.closed));
txt_close.setText(builder);
Instead of this
txt_close.setText(spanString + " " + mContext.getResources().getString(R.string.closed));
Using String templating, you can have a string resource:
<b> indicates bold,
%1$d indicates I am expecting a digit/number
so I get (5 min away) in the textview
//xml
<string name="confirm_eta_text"> <b>%1$d min </b> away</string>
// Java
mEta.setText(
Compat.fromHtml(String.format(getResources().getString(R.string.confirm_eta_text), 5)));
Android String Formatting
I am looking for a way to change the color of a text of a single word in a TextView from within an Activity.
For example, with this:
String first = "This word is ";
String next = "red"
TextView t = (TextView) findViewById(R.id.textbox);
t.setText(first + next);
How would I change the color of the next text to red?
Easiest way I know is to just use html.
String first = "This word is ";
String next = "<font color='#EE0000'>red</font>";
t.setText(Html.fromHtml(first + next));
But this will require you to rebuild the TextView when (if?) you want to change the color, which could cause a hassle.
t.setText(first + next, BufferType.SPANNABLE);
Spannable s = (Spannable)t.getText();
int start = first.length();
int end = start + next.length();
s.setSpan(new ForegroundColorSpan(0xFFFF0000), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
you have to use spannable this will also allows you to increase some text's size, make it bold etc.... even put in some image.
Use SpannableStringBuilder like this :
SpannableStringBuilder builder = new SpannableStringBuilder();
SpannableString str1= new SpannableString("Text1");
str1.setSpan(new ForegroundColorSpan(Color.RED), 0, str1.length(), 0);
builder.append(str1);
SpannableString str2= new SpannableString(appMode.toString());
str2.setSpan(new ForegroundColorSpan(Color.GREEN), 0, str2.length(), 0);
builder.append(str2);
TextView tv = (TextView) view.findViewById(android.R.id.text1);
tv.setText( builder, TextView.BufferType.SPANNABLE);
for long string you can use this:
String help = getString(R.string.help);
help = help.replace("some word", "<font color='#EE0000'>some word</font>");
txtDesc.setText(Html.fromHtml(help));
If you want to change the state of all the instances of a specific String inside a TextView text(case insensitive) you can use StringBuilders and SpannableString like this:
StringBuilder textBuilder = new StringBuilder(myTextView.getText().toString());
StringBuilder searchedTextBuilder = new StringBuilder((mySearchedString));
SpannableString spannableString = new SpannableString(myTextView.getText().toString());
int counter = 0;
int index = 0;
for (int i = 0;i < textBuilder.length() - mySearchedString.length() - 1;i++)
{
counter = 0;
if (Character.toLowerCase(textBuilder.charAt(i)) == Character.toLowerCase(searchedTextBuilder.charAt(index)))
{
counter++;
index++;
for (int j = 1,z = i + 1;j < mySearchedString.length() - 1;j++,z++)
{
if (Character.toLowerCase(textBuilder .charAt(z)) == Character.toLowerCase(searchedTextBuilder .charAt(index)))
{
counter++;
index++;
}
else
{
index++;
if (index % mySearchedString.length() == 0)
{
index = 0;
}
break;
}
}
if (counter == mySearchedString.length() - 1) // A match
{
spannableString.setSpan(new ForegroundColorSpan(Color.RED), i,
i + mySearchedString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // Do the change you want(In this case changing the fore ground color to red)
index = 0;
continue;
}
else
{
index = 0;
continue;
}
}
}
myTextView.setText(spannableString);
}
Store the whole TextView text inside a StringBuilder.
Store the searched string inside a StringBuilder.
Store the wholre TextView text inside a SpannableString
Make a simple operation to find all the String instances inside the TextView text and change them when reached.
Set the text value of the TextView to the SpannableString.
I implemented a utility function in Kotlin for my own usecase and maybe useful for someone else.
fun getCusomTextWithSpecificTextWithDiffColor(textToBold: String, fullText: String,
targetColor: Int) =
SpannableStringBuilder(fullText).apply {
setSpan(ForegroundColorSpan(targetColor),
fullText.indexOf(textToBold),
(fullText.indexOf(textToBold) + textToBold.length),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
How I am using it:
context?.let {
infoMessage.text = AppUtils.getCusomTextWithSpecificTextWithDiffColor(
wordAsBold,
completeSentence, ContextCompat.getColor(it, R.color.white))
}
USE:
makeTextBold("Your order is accepted","accepted", textView);
makeTextBold("Your order is canceled","canceled", textView);
Function:
public static void makeTextBold(String sentence, String word, AppCompatTextView textView) {
SpannableStringBuilder builder = new SpannableStringBuilder();
int startIndex = sentence.indexOf(word.toLowerCase().trim());
int endIndex = startIndex + word.toLowerCase().trim().length();
SpannableString spannableString = new SpannableString(sentence);
StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
spannableString.setSpan(boldSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //To make text Bold
spannableString.setSpan(new ForegroundColorSpan(Color.RED), startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //To change color of text
builder.append(spannableString);
textView.setText(builder, TextView.BufferType.SPANNABLE);
}
I think this is more readable
for coloring a word in a string
it is also probably more efficient a bit because you write once
String str = YOUR_STRING
Spannable s = new SpannableString(str);
int start = str.indexOf(err_word_origin);
int end = start + err_word_origin.length();
s.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
YOUR_TEXT_VIEW.setText(s , TextView.BufferType.SPANNABLE);
my solution extension:
fun coloredText(
baseText: String,
coloredText: String,
targetColor: Int
): SpannableStringBuilder {
val transformText = "$baseText $coloredText"
return SpannableStringBuilder(transformText).apply {
setSpan(
ForegroundColorSpan(targetColor),
transformText.indexOf(coloredText),
(transformText.indexOf(coloredText) + coloredText.length),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
Usage
binding.mytextView.title = coloredText(
baseText = getString(R.string.my_title),
coloredText = getString(R.string.my_title_colored_part),
targetColor = ContextCompat.getColor(requireContext(), R.color.blue))
Iv'e found this best answer
https://stackoverflow.com/a/53573169/14250778
just changed one line to support also words that starts with uppercase letter
public void setHighLightedText(TextView tv, String textToHighlight) {
// added "toLowerCase()" to support words that starts with uppercase letter
String tvt = tv.getText().toString().toLowerCase();
int ofe = tvt.indexOf(textToHighlight, 0);
Spannable wordToSpan = new SpannableString(tv.getText());
for (int ofs = 0; ofs < tvt.length() && ofe != -1; ofs = ofe + 1) {
ofe = tvt.indexOf(textToHighlight, ofs);
if (ofe == -1)
break;
else {
// set color here
wordToSpan.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + textToHighlight.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(wordToSpan, TextView.BufferType.SPANNABLE);
}
}
}