Android: раскрашивание части строки с помощью TextView.setText ()?

87

Я хочу изменить текст представления TextView с помощью метода .setText (""), а также раскрасить часть текста (или сделать его полужирным, курсивом, прозрачным и т. Д.), А не остальное. Например:

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

Я знаю, что приведенный выше код неверен, но он помогает проиллюстрировать, чего я хотел бы достичь. Как мне это сделать?

Джаред
источник
возможный дубликат того, как я могу изменить цветную часть TextView?
живая любовь
Если в TextView есть длинный текст, есть более эффективный способ
Mingfei
Возможный дубликат параметра Установить цвет диапазона TextView в Android
Suragch
Решение в Котлине с использованием Spans stackoverflow.com/a/59510004/11166067
Дмитрий Леонов

Ответы:

203

Используйте пролеты .

Пример:

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, а затем они будут объединены
Филипп
1
В комментарии говорится, что span, чтобы сделать текст жирным, должен ли он сказать, что span, чтобы сделать текст цветным?
Ryhan
9
@philipp, если ваша проблема в том, сколько символов в вашем слове, используйте метод length () для String или StringBuilder или что-то еще
Ахмед Адель Исмаил
1
Если в TextView есть длинный текст, вот более эффективный способ
Mingfei
Я сначала пропустил это при чтении ответа, но ваш конечный индекс должен быть +1 конечный индекс в строке (т.е. чтобы охватить первые четыре буквы, вы должны установить [начало, конец] как [0, 4], а не [0, 3])
tir38
46
title.setText(Html.fromHtml("Your big island <b>ADVENTURE!</b>")); 
сидел
источник
2
Это гораздо более хорошее решение исходной проблемы, чем отмеченный ответ.
BSnapZ 08
1
Если у вас есть разрывы строк \ n, они не отображаются.
live-love
8
Нет, не лучше, здесь нет упомянутой функции раскраски, кроме метода SLOW из HTML ()
Виктор Якунин
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 01
Дополнительные объяснения см. В разделе « Стилизация с разметкой 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"))?
Аджай Пандья,
8

Вы можете использовать a, 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);
Nanne
источник
Как мы можем настроить начальный и конечный диапазон для многоязычного текста?
Mubarak
Одна из идей может заключаться в том, чтобы идентифицировать слово, которое вам нужно выделить, и извлечь его как отдельный строковый ресурс. При переводе фразы вам нужно будет рассмотреть возможность обновления отдельного слова, чтобы при настройке диапазона полагаться на indexOf строки и длину строки для динамической установки начального и конечного индексов диапазона.
Ионут Негру,
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) } } }
Абхишек Саксена
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

Вы можете объединить два или более промежутков. Таким образом легче раскрасить динамический текст, используя значение длины.

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!"));
Хади Примечание
источник
0

Html.fromHtmlявляется устаревшим

Вместо этого используйте HtmlCompat

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY)
Gastón Saillén
источник