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 have a TextView in which I have to set a Text. But I'm adding (Concatenating) some text to it and I want only that concatenated text to get some color but not the whole textstoryLine=storyLine.substring(0,190)+" ...Click To Expand";. Here storyLine is a final text that is to be set in a textview. I just want change color of "Click To Expand".
String cntStr = " ...Click To Expand";
String storyLine = storyLine.substring(0,190);
String textLine = storyLine + cntStr;
Spannable spannable = new SpannableString(textLine);
spannable.setSpan(new ForegroundColorSpan(Color.RED), storyLine.length(), textLine.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
myTextView.setText(spannable, TextView.BufferType.SPANNABLE);
Happy Coding !!!!
You can try
String styledText = storyLine + "<font color='blue'>Click To Expand</font>";
textView.setText(Html.fromHtml(styledText), TextView.BufferType.SPANNABLE);
You can achieve by this :
SpannableStringBuilder builder = new SpannableStringBuilder();
String red = "Click To Expand";
builder.append("storyLine=storyLine.substring(0,190)+" ...");
SpannableString redSpannable= new SpannableString(red);
redSpannable.setSpan(new ForegroundColorSpan(Color.RED), 0, red.length(), 0);
builder.append(redSpannable);
mTextView.setText(builder, BufferType.SPANNABLE);
Happy coding!!
You can use SpannableString to color the sub string.
SpannableString span1=new SpannableString("Hello World...Click to Expand");
span1.setSpan(new ForegroundColorSpan(Color.BLUE), 15, 29, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Textview.setText(span1,TextView.BufferType.SPANNABLE);
You can also concatenate
Textview.setText(TextUtils.concat(AnyString, span1));
Set Texview type spannable in Layout xml if needed.
String records = "<font color='red'>"+edittext.getText().toString()+"</font>.";
textView.setText("Total Records to be SYNC : "+Html.fromHtml(records) +"\nDo you want sync all records...!", TextView.BufferType.SPANNABLE);
here its not displayed in red color
I think you are doing it in wrong way. Check out this answer, it may help you.
How to set the text color of TextView in code?
A variation using just standard color code:
android:textColor="#ff0000"
Add it in XML of TEXTVIEW
or use
textview.setTextColor(color);
SpannableStringBuilder builder = new SpannableStringBuilder();
String red = edittext.getText().toString();
SpannableString redSpannable= new SpannableString(red);
redSpannable.setSpan(new ForegroundColorSpan(Color.RED), 0, red.length(), 0);
builder.append(redSpannable);
mTextView.setText("Total Records to be SYNC : "+builder+"\nDo you want sync all records...!", BufferType.SPANNABLE);
You can do with following code, I have tested and It's working perfect.
String value1 = "Total Records to be SYNC : ";
String value2 = "\nDo you want sync all records...!";
String valueFromEdittext = edittext.getText().toString();
String finalValue = value1 + valueFromEdittext + value2;
Spannable WordtoSpan = new SpannableString(finalValue);
WordtoSpan.setSpan(new ForegroundColorSpan(Color.RED), value1.length(), (value1 + valueFromEdittext).length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
mTextView.setText(WordtoSpan);
I am following this example in using SpannableString:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/text/Link.html
I am trying to create a string which has 'R.string.text1' following by R.string.text2 but R.string.text2 (has 10 characters) in URL format:
SpannableString ss = new SpannableString(getString(R.string.text1));
ss.setSpan(new URLSpan(getString(R.string.text2)), 0, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
But what I am getting is
I don't see the string R.string.text2 at all
and only the first 10 characters is in URL format
How can I fix my problem?
This is a more general answer to show just a basic working example of a URLSpan.
// set up spanned string with url
SpannableString spannableString = new SpannableString("Click here for more.");
String url = "https://developer.android.com";
spannableString.setSpan(new URLSpan(url), 6, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// set to textview
textView.setText(spannableString);
textView.setMovementMethod(LinkMovementMethod.getInstance()); // enable clicking on url span
May i correct you ?
SpannableString ss = new SpannableString(getText(R.string.text1)+" "+getText(R.string.text2));
ss.setSpan(new URLSpan(getString(R.string.text2)),
getString(R.string.text1).length()+1,
ss.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
quite late, but at least done for the others ^^
you can also do it this way :
SpannableString ss1 = new SpannableString(getText(R.string.text1));
// do what you want with ss1
SpannableString ss2 = new SpannableString(getText(R.string.text2)); // the text visible
ss2.setSpan(new URLSpan(getString(R.string.text2)), // this is the link itself
0,
ss2.length(), // link on entire text
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
CharSequence csSS = TextUtils.concat(ss1, ss2); // import android.text.TextUtils;
try this way..
SpannableString ss = new SpannableString(getString(R.string.text1+""+R.string.text2));
ss.setSpan(new URLSpan(getString(R.string.text2)), 0, getString(R.string.text2).length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
In the kotlin, you can use like this way
fun SpannableStringBuilder.urlSpan(value: String): SpannableStringBuilder {
val start = length
this.append(value)
val end = length
this.setSpan(URLSpan(value), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
return this
}
SpannableStringBuilder().urlSpan("www.google.com")