Android: Tô màu một phần của chuỗi bằng TextView.setText ()?


86

Tôi đang tìm cách thay đổi văn bản của chế độ xem TextView thông qua phương thức .setText ("") đồng thời tô màu một phần của văn bản (hoặc làm cho nó đậm, nghiêng, trong suốt, v.v.) chứ không phải phần còn lại. Ví dụ:

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

Tôi biết mã trên là không chính xác nhưng nó giúp minh họa những gì tôi muốn đạt được. Làm thế nào tôi sẽ làm điều này?



Nếu có một văn bản dài trong TextView, Có một cách hiệu quả hơn
Mingfei


Giải pháp trong Kotlin sử dụng nhịp stackoverflow.com/a/59510004/11166067
Dmitrii Leonov

Câu trả lời:


201

Sử dụng các nhịp .

Thí dụ:

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
Tôi thực sự không thích giải pháp mà android cung cấp ở đây, vì nó không hoạt động với đa ngôn ngữ vì tôi không biết có bao nhiêu ký tự trong các từ của mình. Tôi hiện đang tìm kiếm một giải pháp mà tôi có thể có nhiều nhịp mà tôi có thể đính kèm tất cả để một TextView và sau đó chúng được đặt lại với nhau
Philipp

1
Nhận xét nói span để làm cho văn bản in đậm, nó có nên nói span để làm cho văn bản màu?
Ryhan

9
@philipp nếu vấn đề của bạn là bao nhiêu ký tự trong văn bản của bạn, sử dụng phương thức length () trên dây của bạn hoặc StringBuilder hoặc bất cứ điều gì
Ahmed Adel Ismail

1
Nếu có một văn bản dài trong TextView, đây là một cách hiệu quả hơn
Mingfei

Ban đầu tôi đã bỏ lỡ điều này khi đọc câu trả lời, nhưng chỉ mục cuối của bạn phải được +1 chỉ mục kết thúc trong chuỗi (nghĩa là để kéo dài bốn chữ cái đầu tiên, bạn phải đặt [bắt đầu, kết thúc] là [0, 4] chứ không phải [0, 3])
tir38

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

2
Đây là một giải pháp tốt hơn nhiều cho vấn đề ban đầu so với câu trả lời được đánh dấu.
BSnapZ

1
Nếu bạn có ngắt dòng \ n, điều này sẽ không hiển thị ngắt dòng.
live-love

8
Không, nó không phải là đẹp hơn, không có tính năng tô màu, được đề cập trong câu hỏi nhưng phương pháp CHẬM fromHTML ()
Viktor Yakunin

1
Vì vậy, sử dụng <font color="#FFAADD>text</font>sẽ không hoạt động?
milosmns

25

Tôi hy vọng điều này sẽ giúp bạn (nó hoạt động với nhiều ngôn ngữ).

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

Và trên mã java của bạn, bạn có thể làm:

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

Bằng cách này, chỉ phần "Kiểm tra" sẽ được tô màu (và in đậm).


3
Câu trả lời tốt nhất. Điều này hoạt động hoàn hảo cho các chuỗi được quốc tế hóa. Cũng có lợi thế là có thể có văn bản màu ở giữa tài nguyên chuỗi của bạn.
jt-gilkeson

Đối với giải thích thêm thấy Styling với HTML markup phần ở đây .
Elisabeth

17

Đây là một ví dụ sẽ tìm kiếm tất cả các lần xuất hiện của một từ (phân biệt chữ hoa chữ thường) và tô màu đỏ cho chúng:

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

Tôi thích tên của bạn: P Tôi có thể thay đổi nền của từ cụ thể bằng BackgroundColorSpan mới (Color.parseColor ("# BFFFC6")) không?
Ajay Pandya

8

Bạn có thể sử dụng một Spannableđể cung cấp cho các phần nhất định của văn bản những khía cạnh nhất định. Tôi có thể tra cứu một ví dụ nếu bạn muốn.

À, từ ngay đây trên 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);

Làm cách nào để định cấu hình phạm vi bắt đầu và kết thúc cho văn bản đa ngôn ngữ?
Mubarak,

8

Nếu bạn đang sử dụng Kotlin, bạn có thể làm như sau bằng cách sử dụng thư viện android-ktx

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

titleTextField.text = title

Đây boldlà một chức năng mở rộng được bật SpannableStringBuilder. Bạn có thể xem tài liệu tại đây để biết danh sách các thao tác bạn có thể sử dụng.

Một vi dụ khac:

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

Đâu greenlà màu RGB được phân giải.

Thậm chí có thể lồng ghép các nhịp để bạn kết thúc với một thứ giống như DSL được nhúng:

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

Bạn sẽ cần những thứ sau trong cấp mô-đun ứng dụng của mình build.gradleđể nó hoạt động:

repositories {
    google()
}

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

Ngoài ra, bất kể tôi đặt màu nào, nó đều hiển thị cùng một màu tím. val spannableStringBuilder = SpannableStringBuilder() spannableStringBuilder.bold { underline { color(R.color.test_color) { append(underlinedText) } } }
Abhishek Saxena

4

Nếu bạn muốn sử dụng HTML, bạn cần sử dụng TextView.setText(Html.fromHtml(String htmlString))

Nếu bạn muốn làm điều đó thường xuyên / lặp lại, bạn có thể xem qua một lớp ( SpannableBuilder ) mà tôi đã viết, vì Html.fromHtml()nó không hiệu quả lắm (nó đang sử dụng một bộ máy phân tích cú pháp xml lớn bên trong). Nó được mô tả trong bài đăng trên blog này .


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

Sử dụng

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

textView.setText(spannable);

nhập mô tả hình ảnh ở đây


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

hoặc sử dụng mã này:

    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

Tôi thích sử dụng SpannableStringBuilderbằng cách nối từng nhịp khác nhau, thay vì gọi setSpan bằng cách tính toán độ dài chuỗi

như: (mã 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)
}

Kết quả


2

Bạn có thể nối hai hoặc nhiều Spans. Cách này dễ dàng hơn để tô màu văn bản động bằng cách sử dụng giá trị độ dài.

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

Sử dụng mã này hữu ích

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.