Android: Mewarnai bagian string menggunakan TextView.setText ()?

88

Saya ingin mengubah teks dari tampilan TextView melalui metode .setText ("") sambil juga mewarnai bagian teks (atau membuatnya tebal, miring, transparan, dll.) Dan bukan yang lainnya. Sebagai contoh:

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

Saya tahu kode di atas tidak benar tetapi ini membantu menggambarkan apa yang ingin saya capai. Bagaimana saya melakukan ini?

Jared
sumber
Jika ada teks panjang di TextView, Ada cara yang lebih efisien
Mingfei
Kemungkinan duplikat warna Set rentang TextView di Android
Suragch
Solusi di Kotlin menggunakan Spans stackoverflow.com/a/59510004/11166067
Dmitrii Leonov

Jawaban:

203

Gunakan rentang waktu .

Contoh:

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
sumber
11
Saya benar-benar tidak suka solusi yang ditawarkan android di sini, karena tidak berfungsi dengan multi bahasa karena saya tidak tahu berapa banyak karakter dalam kata-kata saya. Saat ini saya mencari solusi di mana saya dapat memiliki beberapa bentang yang dapat saya lampirkan semuanya ke TextView dan kemudian disatukan
philipp
1
Komentar mengatakan span untuk membuat teks tebal, haruskah dikatakan span untuk membuat warna teks?
Ryhan
9
@philipp jika masalah Anda adalah berapa banyak karakter dalam kata Anda, gunakan metode length () pada String atau StringBuilder Anda atau apa pun
Ahmed Adel Ismail
1
Jika ada teks panjang di TextView, berikut adalah cara yang lebih efisien
Mingfei
Awalnya saya melewatkan ini ketika membaca jawabannya, tetapi indeks akhir Anda harus +1 indeks akhir dalam string (yaitu untuk menjangkau empat huruf pertama Anda harus menetapkan [awal, akhir] sebagai [0, 4] bukan [0, 3])
tir38
46
title.setText(Html.fromHtml("Your big island <b>ADVENTURE!</b>")); 
duduk
sumber
2
Ini adalah solusi yang jauh lebih baik untuk masalah asli daripada jawaban yang ditandai.
BSnapZ
1
Jika Anda memiliki jeda baris \ n, ini tidak menampilkan jeda baris.
cinta langsung
8
Tidak, ini tidak lebih bagus, tidak ada fitur pewarnaan, yang disebutkan dalam pertanyaan, tetapi metode SLOW dariHTML ()
Viktor Yakunin
1
Jadi menggunakan <font color="#FFAADD>text</font>tidak akan berhasil?
milosmns
25

Saya harap ini membantu Anda (ini bekerja dengan multi bahasa).

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

Dan pada kode java Anda, Anda dapat melakukan:

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

Dengan cara ini, hanya bagian "Test" yang akan diwarnai (dan dicetak tebal).

Luis
sumber
3
Jawaban Terbaik. Ini berfungsi sempurna untuk string internasional. Juga memiliki keuntungan karena dapat menempatkan teks berwarna Anda di tengah sumber daya string Anda.
jt-gilkeson
Untuk penjelasan lebih lanjut, lihat bagian Styling dengan markup HTML di sini .
Elisabeth
17

Berikut adalah contoh yang akan mencari semua kemunculan sebuah kata (case insensitive), dan mewarnainya dengan merah:

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);
cinta hidup
sumber
saya suka nama Anda: P Dapatkah saya mengubah latar belakang kata tertentu dengan BackgroundColorSpan (Color.parseColor ("# BFFFC6")) baru?
Ajay Pandya
9

Jika Anda menggunakan Kotlin, Anda dapat melakukan hal berikut menggunakan pustaka android-ktx

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

titleTextField.text = title

Ini boldadalah fungsi ekstensi di SpannableStringBuilder. Anda dapat melihat dokumentasi di sini untuk daftar operasi yang dapat Anda gunakan.

Contoh lain:

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

Dimana greenwarna RGB terselesaikan.

Bahkan dimungkinkan untuk membuat rentang bersarang sehingga Anda berakhir dengan sesuatu seperti DSL tertanam:

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

Anda akan membutuhkan yang berikut ini di level modul aplikasi Anda build.gradleagar berfungsi:

repositories {
    google()
}

dependencies {
    implementation 'androidx.core:core-ktx:0.3'
}
David Rawson
sumber
Juga, apapun warna yang saya pakai, itu menunjukkan warna ungu yang sama. val spannableStringBuilder = SpannableStringBuilder() spannableStringBuilder.bold { underline { color(R.color.test_color) { append(underlinedText) } } }
Abhishek Saxena
8

Anda dapat menggunakan file Spannable untuk memberikan bagian tertentu dari teks aspek tertentu. Saya dapat mencari contoh jika Anda mau.

Ah, dari sini di 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
sumber
Bagaimana kita bisa mengonfigurasi rentang awal dan akhir untuk teks multi bahasa?
Mubarak
Salah satu idenya adalah mengidentifikasi kata yang perlu Anda sorot dan mengekstraknya sebagai sumber string terpisah. Saat menerjemahkan frase, Anda perlu mempertimbangkan untuk memperbarui kata yang terpisah juga sehingga ketika Anda menyetel span untuk bergantung pada indexOf string dan panjang string untuk secara dinamis menyetel indeks awal dan akhir span.
Ionut Negru
4

Jika Anda ingin menggunakan HTML, Anda perlu menggunakan TextView.setText(Html.fromHtml(String htmlString))

Jika Anda ingin melakukannya sering / berulang kali, Anda dapat melihat kelas ( SpannableBuilder ) yang saya tulis, karena Html.fromHtml()tidak terlalu efisien (menggunakan mesin parsing xml besar di dalamnya). Itu dijelaskan dalam posting blog ini .

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

Menggunakan

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

textView.setText(spannable);

masukkan deskripsi gambar di sini

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

atau gunakan kode ini:

    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
sumber
3

Saya suka menggunakan SpannableStringBuilderdengan menambahkan span yang berbeda satu per satu, daripada memanggil setSpan dengan menghitung panjang string

sebagai: (kode Kotlin)

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

Hasil

vedant
sumber
2

Anda dapat menggabungkan dua atau lebih Span. Cara ini lebih mudah untuk mewarnai teks dinamis menggunakan nilai panjang.

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
sumber
2

Gunakan kode ini untuk membantu

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

Html.fromHtml adalah usang

Gunakan HtmlCompat sebagai gantinya

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