Android: Teil eines Strings mit TextView.setText () färben?

86

Ich möchte den Text einer TextView-Ansicht über die Methode .setText ("") ändern und gleichzeitig einen Teil des Textes einfärben (oder fett, kursiv, transparent usw. machen) und nicht den Rest. Beispielsweise:

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

Ich weiß, dass der obige Code falsch ist, aber er hilft zu veranschaulichen, was ich erreichen möchte. Wie würde ich das machen?

Jared
quelle
Wenn die Textansicht einen langen Text enthält, gibt es einen effizienteren Weg
Mingfei,
Mögliches Duplikat von Set color of TextView span in Android
Suragch
Lösung in Kotlin mit Spans stackoverflow.com/a/59510004/11166067
Dmitrii Leonov

Antworten:

201

Verwenden Sie Spannweiten .

Beispiel:

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);
Alex Orlov
quelle
10
Ich mag die Lösung, die Android hier anbietet, wirklich nicht, da sie nicht mit mehreren Sprachen funktioniert, da ich keine Ahnung habe, wie viele Zeichen in meinen Worten sind. Ich bin derzeit auf der Suche nach einer Lösung, bei der ich mehrere Bereiche haben kann, die ich alle an eine Textansicht anhängen kann, und die dann zusammengesetzt werden
philipp
1
Der Kommentar sagt span, um Text fett zu machen, sollte es span sagen, um Textfarbe zu machen?
Ryan
9
@philipp Wenn Ihr Problem darin besteht, wie viele Zeichen in Ihrem Wort enthalten sind, verwenden Sie die length () -Methode für Ihren String oder StringBuilder oder was auch immer
Ahmed Adel Ismail
1
Wenn die Textansicht einen langen Text enthält, ist dies ein effizienterer Weg
Mingfei,
Ich habe dies beim Lesen der Antwort zunächst übersehen, aber Ihr Endindex muss +1 der Endindex in der Zeichenfolge sein (dh um die ersten vier Buchstaben zu überspannen, müssen Sie [Start, Ende] als [0, 4] und nicht als [0, 3])
tir38
46
title.setText(Html.fromHtml("Your big island <b>ADVENTURE!</b>")); 
saß
quelle
2
Dies ist eine weitaus schönere Lösung für das ursprüngliche Problem als die markierte Antwort.
BSnapZ
1
Wenn Sie Zeilenumbrüche haben \ n, werden die Zeilenumbrüche nicht angezeigt.
Live-Liebe
8
Nein, es ist nicht schöner, es gibt keine Farbfunktion, die in Frage kommt, sondern die langsame Methode von HTML ()
Viktor
1
Die Verwendung <font color="#FFAADD>text</font>funktioniert also nicht?
Milosmns
25

Ich hoffe das hilft dir (es funktioniert mit mehreren Sprachen).

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

Und mit Ihrem Java-Code können Sie Folgendes tun:

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

Auf diese Weise wird nur der Teil "Test" farbig (und fett) dargestellt.

Luis
quelle
3
Beste Antwort. Dies funktioniert perfekt für internationalisierte Saiten. Hat auch den Vorteil, dass Sie Ihren farbigen Text in der Mitte Ihrer Zeichenfolgenressource haben können.
Jt-Gilkeson
Weitere Erläuterungen finden Sie in den Styling mit HTML - Markup Abschnitt hier .
Elisabeth
17

Hier ist ein Beispiel, das nach allen Vorkommen eines Wortes sucht (ohne Berücksichtigung der Groß- und Kleinschreibung) und sie rot färbt:

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);
Live-Liebe
quelle
Ich liebe deinen Namen: P Kann ich den Hintergrund eines bestimmten Wortes mit dem neuen BackgroundColorSpan (Color.parseColor ("# BFFFC6")) ändern?
Ajay Pandya
8

Sie können a verwenden Spannable, um bestimmten Teilen eines Textes bestimmte Aspekte zuzuweisen. Ich kann ein Beispiel nachschlagen, wenn Sie wollen.

Ah, von hier aus auf 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
quelle
Wie können wir den Start- und Endbereich für mehrsprachigen Text konfigurieren?
Mubarak
7

Wenn Sie Kotlin verwenden, können Sie mit der android-ktx- Bibliothek Folgendes tun

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

titleTextField.text = title

Das boldist eine Erweiterungsfunktion an SpannableStringBuilder. In der Dokumentation finden Sie eine Liste der Vorgänge, die Sie verwenden können.

Ein anderes Beispiel:

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

Wo greenist eine aufgelöste RGB-Farbe.

Es ist sogar möglich, Bereiche zu verschachteln, sodass Sie so etwas wie ein eingebettetes DSL erhalten:

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

Sie benötigen Folgendes in Ihrer App-Modulebene, build.gradledamit es funktioniert:

repositories {
    google()
}

dependencies {
    implementation 'androidx.core:core-ktx:0.3'
}
David Rawson
quelle
Egal welche Farbe ich habe, es zeigt auch die gleiche lila Farbe. val spannableStringBuilder = SpannableStringBuilder() spannableStringBuilder.bold { underline { color(R.color.test_color) { append(underlinedText) } } }
Abhishek Saxena
4

Wenn Sie HTML verwenden möchten, müssen Sie verwenden TextView.setText(Html.fromHtml(String htmlString))

Wenn Sie dies häufig / wiederholt tun möchten, können Sie sich eine Klasse ( SpannableBuilder ) ansehen, die ich geschrieben habe, da sie Html.fromHtml()nicht sehr effizient ist (sie verwendet eine große XML-Parsing-Maschinerie im Inneren). Es wird in diesem Blogeintrag beschrieben .

Heiko Rupp
quelle
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);
    }
}

Verwenden von

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

textView.setText(spannable);

Geben Sie hier die Bildbeschreibung ein

Phan Van Linh
quelle
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));

oder verwenden Sie diesen 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);

Nur Gazi
quelle
3

Ich verwende es gerne, SpannableStringBuilderindem ich die verschiedenen Bereiche einzeln anhänge, anstatt setSpan durch Berechnung der Zeichenfolgenlängen aufzurufen

als: (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)
}

Ergebnis

vedant
quelle
2

Sie können zwei oder mehr Bereiche verketten. Auf diese Weise ist es einfacher, dynamischen Text mithilfe des Längenwerts einzufärben.

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);
Jorge Palacio
quelle
2

Verwenden Sie diesen Code, es ist hilfreich

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

Html.fromHtmlist veraltet

Verwenden Sie stattdessen HtmlCompat

HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY)
Gastón Saillén
quelle