Android:使用TextView.setText()对字符串的一部分进行着色?


86

我想通过.setText(“”)方法更改TextView视图的文本,同时还要给文本的一部分上色(或使其变为粗体,斜体,透明等),而不是其余部分。例如:

title.setText("Your big island <b>ADVENTURE!</b>";

我知道上面的代码是错误的,但是它有助于说明我想要实现的目标。我该怎么做?



如果在TextView的长文,有一个更有效的方式
鸣飞


使用跨度的Kotlin解决方案stackoverflow.com/a/59510004/11166067
Dmitrii Leonov

Answers:


201

使用跨度

例:

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

11
我真的不喜欢android在这里提供的解决方案,因为它不支持多语言,因为我不知道我的单词有多少个字符。我目前正在寻找一种解决方案,其中可以具有多个跨度,可以将所有跨度附加到TextView,然后将它们放在一起
philipp

1
评论说跨度使文本变为粗体,应该说跨度使文本变为彩色吗?
雷汉

9
@philipp如果您的问题是单词中有多少个字符,请在String或StringBuilder或任何其他方法上使用length()方法
Ahmed Adel Ismail

1
如果TextView中有长文本,这是一种更有效的方法
Mingfei 2015年

我最初在阅读答案时会错过这一点,但是您的结束索引必须是字符串中结束索引的+1(例如,要跨越前四个字母,您必须将[start,end]设置为[0,4]而不是[0, 3])
tir38 '16

46
title.setText(Html.fromHtml("Your big island <b>ADVENTURE!</b>")); 

2
与标记的答案相比,这是对原始问题的更好解决方案。
BSnapZ 2014年

1
如果您有换行符\ n,则不会显示换行符。
现场直播

8
不,它不是更好,没有着色功能,有人提到过,但是来自HTML()的SLOW方法
Viktor

1
那么使用<font color="#FFAADD>text</font>将不起作用?
milosmns

25

希望对您有所帮助(它适用于多种语言)。

<string name="test_string" ><![CDATA[<font color="%1$s"><b>Test/b></font>]]> String</string>

在Java代码上,您可以执行以下操作:

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

这样,只有“测试”部分将被上色(加粗)。


3
最佳答案。这非常适合国际化的字符串。还具有能够将彩色文本放在字符串资源中间的优点。
jt-gilkeson 2015年

有关更多说明,请参见此处的HTML样式样式部分。
伊丽莎白

17

这是一个示例,该示例将查找所有出现的单词(不区分大小写),然后将它们涂成红色:

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

我爱你的名字:P我可以用新的BackgroundColorSpan(Color.parseColor(“#BFFFC6”))更改特定单词的背景吗?
Ajay Pandya

8

您可以使用Spannable赋予文本的某些部分某些方面。如果您愿意,我可以举个例子。

啊,从这里开始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);

我们如何配置多语言文本的开始和结束范围?
穆巴拉克

8

如果您使用的是Kotlin,则可以使用android-ktx库执行以下操作

val title = SpannableStringBuilder()
        .append("Your big island ")
        .bold { append("ADVENTURE") } 

titleTextField.text = title

bold是一个扩展功能SpannableStringBuilder。您可以在此处查看文档以获取可以使用的操作列表。

另一个例子:

val ssb = SpannableStringBuilder()
            .color(green) { append("Green text ") }
            .append("Normal text ")
            .scale(0.5F) { append("Text at half size ") }
            .backgroundColor(green) { append("Background green") }

green解析的RGB颜色在哪里。

甚至有可能嵌套跨度,因此最终会出现嵌入式DSL之类的东西:

bold { underline { italic { append("Bold and underlined") } } }

您需要在您的应用程序模块级别中执行build.gradle以下操作才能使其正常工作:

repositories {
    google()
}

dependencies {
    implementation 'androidx.core:core-ktx:0.3'
}

另外,无论我使用哪种颜色,它都显示相同的紫色。 val spannableStringBuilder = SpannableStringBuilder() spannableStringBuilder.bold { underline { color(R.color.test_color) { append(underlinedText) } } }
Abhishek Saxena

4

如果要使用HTML,则需要使用 TextView.setText(Html.fromHtml(String htmlString))

如果您想经常/重复地这样做,可以看看我写的一个类(SpannableBuilder),因为Html.fromHtml()它效率不高(它在内部使用了一个大型的xml解析机制)。在此博客文章中对此进行了描述。


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

使用

Spannable spannable = new SpannableString("Your big island ADVENTURE");
Utils.setColorForPath(spannable, new String[] { "big", "ADVENTURE" }, Color.BLUE);

textView.setText(spannable);

在此处输入图片说明


3

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

或使用以下代码:

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


3

我喜欢SpannableStringBuilder通过一一追加不同的跨度来使用,而不是通过计算字符串长度来调用setSpan

如:(科特林代码)

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

结果


2

您可以串联两个或多个Span。这种方法更容易使用长度值为动态文本着色。

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

2

使用此代码有帮助

TextView txtTest = (TextView) findViewById(R.id.txtTest);
txtTest.setText(Html.fromHtml("This is <font color="#ff4343">Red</font> Color!"));

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.