Android: การระบายสีส่วนของสตริงโดยใช้ TextView.setText ()?


88

ฉันต้องการเปลี่ยนข้อความของมุมมอง TextView โดยใช้เมธอด. setText ("") ในขณะที่ระบายสีส่วนหนึ่งของข้อความ (หรือทำให้เป็นตัวหนาตัวเอียงโปร่งใส ฯลฯ ) ไม่ใช่ส่วนที่เหลือ ตัวอย่างเช่น:

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

ฉันรู้ว่ารหัสด้านบนไม่ถูกต้อง แต่ช่วยอธิบายสิ่งที่ฉันต้องการบรรลุได้ ฉันจะทำอย่างไร



หากมีข้อความยาวใน TextView มีวิธีที่มีประสิทธิภาพมากขึ้น
Mingfei


วิธีแก้ปัญหาใน Kotlin โดยใช้ Spans stackoverflow.com/a/59510004/11166067
Dmitrii Leonov

คำตอบ:


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 หรืออะไรก็ได้
Ahmed Adel Ismail

1
หากมีข้อความยาวใน TextView นี่เป็นวิธีที่มีประสิทธิภาพมากขึ้น
Mingfei

ตอนแรกฉันพลาดสิ่งนี้เมื่ออ่านคำตอบ แต่ดัชนีท้ายของคุณจะต้อง +1 ดัชนีสิ้นสุดในสตริง (กล่าวคือเพื่อขยายตัวอักษรสี่ตัวแรกคุณต้องตั้งค่า [start, end] เป็น [0, 4] ไม่ใช่ [0, 3])
tir38

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

2
นี่เป็นวิธีแก้ปัญหาเดิมที่ดีกว่าคำตอบที่ทำเครื่องหมายไว้
BSnapZ

1
หากคุณมีตัวแบ่งบรรทัด \ n จะไม่แสดงตัวแบ่งบรรทัด
live-love

9
ไม่มันไม่ดีกว่าไม่มีคุณสมบัติการระบายสีที่กล่าวถึงในคำถาม แต่วิธีการช้าจาก HTML ()
Viktor Yakunin

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

สำหรับคำอธิบายเพิ่มเติมโปรดดูที่จัดแต่งทรงผมด้วย HTML มาร์กอัปส่วนที่นี่
Elisabeth

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")) ได้หรือไม่
Ajay Pandya

9

หากคุณใช้ 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) } } }
Abhishek Saxena

8

คุณสามารถใช้ a Spannableเพื่อระบุลักษณะบางส่วนของข้อความ ฉันสามารถดูตัวอย่างได้ถ้าคุณต้องการ

Ah จากที่นี่ใน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);

เราจะกำหนดค่าช่วงเริ่มต้นและสิ้นสุดสำหรับข้อความหลายภาษาได้อย่างไร
Mubarak

แนวคิดอย่างหนึ่งคือการระบุคำที่คุณต้องการเน้นและแยกออกเป็นทรัพยากรสตริงแยกต่างหาก เมื่อแปลวลีคุณจะต้องพิจารณาอัปเดตคำที่แยกจากกันด้วยเพื่อที่ว่าเมื่อคุณตั้งค่าช่วงให้พึ่งพาดัชนีของสตริงและความยาวสตริงเพื่อตั้งค่าดัชนีเริ่มต้นและสิ้นสุดของช่วงแบบไดนามิก
Ionut Negru

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 โดยการคำนวณความยาวสตริง

เป็น: (รหัส 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)
}

ผลลัพธ์


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


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.