单一的TextView,具有多种颜色的文本

214

正如标题所述,我想知道是否有可能在单个textview元素中实现两种不同的颜色。


3
可能是 Is it possible to have multiple styles inside a TextView? 的重复问题。 - dogbane
2
这并不是重复问题,因为提问者特别询问了颜色。 - Iqbal
这方面有一个不错的库,我认为可以使用:https://blog.stylingandroid.com/rialto-downloadable-fonts/ https://github.com/StylingAndroid/Rialto - android developer
我也写了一些库,其行为类似于这个:https://github.com/ha-yi/MultiColorTextView - Hayi Nukman
23个回答

368

是的,如果你使用 htmlfont-color 属性格式化 String,然后将其传递给方法 Html.fromHtml(your text here)

String text = "<font color=#cc0029>First Color</font> <font color=#ffcc00>Second Color</font>";
yourtextview.setText(Html.fromHtml(text));

11
请不要忘记使用Html.escapeHtml(str)来转义用户输入。 - kelunik
多么可爱的答案.... <3 我尝试使用了六个TextView来实现文本样式的多样性,结果真是太烦人了! - RestInPeace
不错的解决方案.. 但我想问一下,它适用于所有Android操作系统版本吗? - hitesh141
我希望有一种方法可以在不编写代码的情况下完成它。不确定为什么这么简单的东西没有在 T.V. 中实现。 - JPM
3
警告:当我需要将文本转换为大写时,有一个问题。我在XML中使用android:textAllCaps="true",同时我的HTML内容也是大写的。但它并没有起作用。我删除了XML属性,现在工作得很好。请注意,如果你在代码中使用setAllCaps(),同样会出现同样的问题。 - joao2fast4u
10
Html.fromHtml(String)现已被弃用,建议改为Html.fromHtml(String, Html.FROM_HTML_MODE_LEGACY)更多信息可以在这里找到 - JediBurrell

194

您可以不使用HTML打印多彩线条,例如:

TextView textView = (TextView) findViewById(R.id.mytextview01);
Spannable word = new SpannableString("Your message");        

word.setSpan(new ForegroundColorSpan(Color.BLUE), 0, word.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

textView.setText(word);
Spannable wordTwo = new SpannableString("Your new message");        

wordTwo.setSpan(new ForegroundColorSpan(Color.RED), 0, wordTwo.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.append(wordTwo);

1
对我来说不起作用,出现了 java.lang.StringIndexOutOfBoundsException: length=3; index=12 的错误。 - Muhammad Babar
2
StringIndexOutOfBoundsException本身就很说明问题了。您正在访问超出其长度的字符串。 - Swapnil Kotwal
谢谢@Swapnil!我下面添加了一个答案,展示如何使用Spannable处理单个字符,如果有帮助的话=) - Casey Murray
1
我的字符串没有被固定,因此字符串将在应用程序运行时生成。我尝试了几乎所有这个问题的答案。但只有这个解决方案对我有效。 - Md. Sabbir Ahmed
1
完美的解决方案,简洁明了。已发布此答案的 Kotlin 版本。干杯! - Dan Abnormal
显示剩余4条评论

43
我已经按照以下方式完成:

查看参考

通过传递字符串颜色设置文本颜色

private String getColoredSpanned(String text, String color) {
    String input = "<font color=" + color + ">" + text + "</font>";
    return input;
}

通过调用以下代码,在 TextView / Button / EditText 等控件上设置文本:

TextView:

TextView txtView = (TextView)findViewById(R.id.txtView);

获取有色字符串:

String name = getColoredSpanned("Hiren", "#800000");
String surName = getColoredSpanned("Patel","#000080");

使用不同颜色的两个字符串设置TextView的文本:

txtView.setText(Html.fromHtml(name+" "+surName));

完成


1
旧闻,从API 24开始,HTml.fromHtml已被弃用。 - Anuraj R
2
你可以将对 Html.fromHtml("...") 的调用替换为对 Html.fromHtml("...", FROM_HTML_MODE_LEGACY) 的调用。 - stkent

41
你可以使用Spannable来为TextView应用效果:
这是一个示例,只为TextView文本的第一部分着色(同时允许您动态设置颜色,而不像HTML示例那样硬编码到字符串中!)
    mTextView.setText("Red text is here", BufferType.SPANNABLE);
    Spannable span = (Spannable) mTextView.getText();
    span.setSpan(new ForegroundColorSpan(0xFFFF0000), 0, "Red".length(),
             Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

在这个例子中,您可以使用getResources().getColor(R.color.red)来替换0xFFFF0000。

1
如果您需要将字符串转换为大写字母,只需使用 toUpperCase() 函数即可。 - Graeme

35

使用SpannableStringBuilder

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);

12

我已经做过这个了,你可以试试:

TextView textView=(TextView)findViewById(R.id.yourTextView);//init

//here I am appending two string into my textView with two diff colors.
//I have done from fragment so I used here getActivity(), 
//If you are trying it from Activity then pass className.this or this; 

textView.append(TextViewUtils.getColoredString(getString(R.string.preString),ContextCompat.getColor(getActivity(),R.color.firstColor)));
textView.append(TextViewUtils.getColoredString(getString(R.string.postString),ContextCompat.getColor(getActivity(),R.color.secondColor)));

在你的TextViewUtils类中添加这个方法:

 /***
 *
 * @param mString this will setup to your textView
 * @param colorId  text will fill with this color.
 * @return string with color, it will append to textView.
 */
public static Spannable getColoredString(String mString, int colorId) {
    Spannable spannable = new SpannableString(mString);
    spannable.setSpan(new ForegroundColorSpan(colorId), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    Log.d(TAG,spannable.toString());
    return spannable;
}

我刚刚更新了,你可以检查一下,对我来说它正常工作。 - Abdul Rizwan
也许您可以使用Html.fromHtml来使用此字符串? - Sergey Shustikov
在string.xml文件中,我创建了一个变量并设置了它,目前它对我有效。现在你能否把你的字符串给我吗? - Abdul Rizwan

10

最好使用strings文件中的字符串,例如:

    <string name="some_text">
<![CDATA[normal color <font color=\'#06a7eb\'>special color</font>]]>
    </string>

使用方法:

textView.text=HtmlCompat.fromHtml(getString(R.string.some_text), HtmlCompat.FROM_HTML_MODE_LEGACY)

8

我不知道从什么时候开始,这是可能的,但您可以简单地将<font> </font>添加到您的string.xml中,这将自动更改每个文本的颜色。无需添加任何其他代码,如spannable text等。

示例

<string name="my_formatted_text">
    <font color="#FF0707">THIS IS RED</font>
    <font color="#0B132B">AND NOW BLUE</font>
</string>

8
@Swapnil Kotwal答案的Kotlin版本。 Android Studio 4.0.1,Kotlin 1.3.72。
val greenText = SpannableString("This is green,")
greenText.setSpan(ForegroundColorSpan(resources.getColor(R.color.someGreenColor), null), 0, greenText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
yourTextView.text = greenText

val yellowText = SpannableString("this is yellow, ")
yellowText.setSpan(ForegroundColorSpan(resources.getColor(R.color.someYellowColor), null), 0, yellowText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
yourTextView.append(yellowText)

val redText = SpannableString("and this is red.")
redText.setSpan(ForegroundColorSpan(resources.getColor(R.color.someRedColor), null), 0, redText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
yourTextView.append(redText)

6
使用 Kotlin 和 Extensions,您可以非常简单和干净地添加彩色文本:
创建一个名为 TextViewExtensions.kt 的文件,并添加以下内容:
fun TextView.append(string: String?, @ColorRes color: Int) {
    if (string == null || string.isEmpty()) {
        return
    }

    val spannable: Spannable = SpannableString(string)
    spannable.setSpan(
        ForegroundColorSpan(ContextCompat.getColor(context, color)),
        0,
        spannable.length,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    )

    append(spannable)
}

现在很容易附加带有颜色的文本

textView.text = "" // Remove old text
textView.append("Red Text", R.color.colorAccent)
textView.append("White Text", android.R.color.white)

基本上与@Abdul Rizwan的答案相同,但使用Kotlin、扩展、一些验证和在扩展中获取颜色。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接