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?



Wenn die Textansicht einen langen Text enthält, gibt es einen effizienteren Weg
Mingfei,


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

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

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.


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

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

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

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 .


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


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


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


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

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.