Change text color of one word in a TextView
Asked Answered
F

11

106

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?

Furmenty answered 28/8, 2011 at 15:42 Comment(3)
Possible duplicate of Is it possible to have multiple styles inside a TextView?Dentilabial
#9754576Cayuga
https://mcmap.net/q/50268/-how-can-we-have-searched-characters-colored-when-we-use-searchview-in-recyclerviewVogeley
W
187

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.

Waxen answered 28/8, 2011 at 15:50 Comment(7)
This is definitely the simplest way but shouldn't the color be color='#EE0000' the pound symbol is needed to denote a hexadecimal color.Caltanissetta
Fixed, thanks! I don't recall if I copied this from actual code or from memory with a color generator website so it might not have worked before.Waxen
Ok just making sure! Also, as I found out you cannot use 8-digit hex codes so no alpha component. That one stumped me for a moment.Caltanissetta
Using fromHtml is deprecated nowGagliano
Html.fromHtml is deprecated. This solution worked for me!Philbert
use HtmlCompat.fromHtmlPsychopathy
DO NOT USE THIS approach if your minimum SDK is 21 or lower since HtmlCompat.fromHtml color style does not work on older version. Instead use SpannableStringBuilder with ForegroundColorSpan or BackgroundColorSpan for a reliable solution.Evenson
N
79
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.

Neelyneeoma answered 28/8, 2011 at 15:52 Comment(5)
Good answer, thanks. In this case "s.length()" can be used instead of "start + next.length()": int end = s.length();Demur
In case anyone looking for Xamarin.Android Solution. You can assign SpannableString object by using TextFormatted Property of your control.Desiderate
Could not get this working. Ended up going with B K's solution.Kurtzman
1. if there is a build it's always better to use it. 2. what didn't work for u ? this solution is old, very old, some apis have changed, added, removed, bug fixed, what exactly failed to work ?Neelyneeoma
I get java.lang.String cannot be cast to android.text.Spannable error.Calista
B
45

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);
Boadicea answered 30/8, 2016 at 4:35 Comment(2)
Is there something I can replace new ForegroundColorSpan(Color) with to make the text retain its original default color?Amidase
How to add plain text(String) in middle of textview ?Endomorph
P
6

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));
Perennial answered 30/3, 2018 at 10:48 Comment(0)
N
3

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.
Nadiya answered 7/5, 2016 at 15:30 Comment(0)
C
2

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);
}
Correlate answered 18/7, 2019 at 7:37 Comment(0)
M
2

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);
Monkish answered 28/10, 2019 at 19:4 Comment(0)
T
1

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))
    }
Tilefish answered 12/7, 2018 at 14:59 Comment(0)
M
1

Iv'e found this best answer https://mcmap.net/q/50269/-highlight-text-inside-a-textview 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);
            }
        }
    }
Mafaldamafeking answered 22/9, 2021 at 23:52 Comment(0)
T
0

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))
Twigg answered 19/6, 2021 at 2:15 Comment(0)
M
0

You could go this easy:

<string>what ever <font color="#121212">IMPORTANT</font> text you want </string>

For a result like this:

enter image description here

You then could use more of the resources for strings, such as bold, italics or others supported.

https://developer.android.com/guide/topics/resources/string-resource

I'm new to android... but you guys put too much effort and little documentation for such small things.

Maestricht answered 30/1 at 21:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.