วิธีสร้างข้อความเฉพาะบน TextView BOLD


252

ฉันไม่รู้ว่าจะสร้างข้อความเฉพาะบน TextView ให้เป็นตัวหนาได้อย่างไร

มันเป็นอย่างนี้

txtResult.setText(id+" "+name);

ฉันต้องการให้ผลลัพธ์เป็นเช่นนี้:

1111นีล

idและnameเป็นตัวแปรที่ฉันได้รับค่าจากฐานข้อมูลและฉันต้องการทำให้เป็นidตัวหนา แต่เพียงidเพื่อที่nameจะไม่ได้รับผลกระทบฉันไม่รู้ว่าจะทำอย่างไร



คำตอบ:


379

เพียงสร้างสตริงของคุณใน HTML และตั้งค่า:

String sourceString = "<b>" + id + "</b> " + name; 
mytextview.setText(Html.fromHtml(sourceString));

5
เนื่องจาก fromHtml (sourceString) เลิกใช้แล้วใน API 24 คุณต้องใช้รหัสถัดไป: Spanned DurationSpanned; if (android.os.Build.VERSION.SDK_INT> = android.os.Build.VERSION_CODES.N) {durationSpanned = Html.fromHtml (DurationFormatted, Html.FROM_HTML_MODE_LEGACY); } else {durationSpanned = Html.fromHtml (DurationFormatted); }
Mladen Rakonjac

2
นี่เป็นตัวเลือกเดียวที่จะใช้งานได้หากคุณทำการแปลแอพของคุณ
howettl

วิธีการแก้ปัญหาที่ดี แต่ผมพบว่ามันไม่ทำงานสำหรับ <และ> @ wtsang02 วิธีการแก้ปัญหาที่เหมาะสมมากขึ้น
โอมาร์ boshra

มันไม่ได้ทำงานกับ <ถ้าคุณใช้ String.format เว้นแต่คุณยังหลบหนีวงเล็บตามที่อธิบายไว้ที่นี่
Yusuf X

5
Html.fromHtml()เลิกใช้แล้วตอนนี้
คนอยู่ที่อื่นที่

384

ในขณะที่คุณสามารถใช้Html.fromHtml ()คุณสามารถใช้วิธีการแบบเนทีฟซึ่งเป็นSpannableStringBuilderแต่โพสต์นี้อาจมีประโยชน์

SpannableStringBuilder str = new SpannableStringBuilder("Your awesome text");
str.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), INT_START, INT_END, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv=new TextView(context);
tv.setText(str);

หากคำตอบนี้ใช้งานไม่ได้ให้ลองต่อท้ายข้อความของคุณด้วยสตริงที่สามารถขยายได้บางสิ่งเช่น: mSpannable.append (yourremainingtext);
Gowtham Kumar

11
สำหรับผู้ที่มาจาก Google โดยที่ไม่เคยมีความรู้มาก่อน: INT_START / INT_END เป็นสถานที่ที่ตัวหนาควรเริ่มต้นและสิ้นสุด
ปอตไลท์

2
ถ้าคุณต้องการใช้มาร์กอัปบางอย่างกับสตริงซอร์สโดยไม่ต้องเปลี่ยนมันคุณควรใช้คลาส
SpannableString

26
การทำเช่นนี้จะพังถ้าคุณต้องการแปลสำเนาของคุณ INT_START และ INT_END จะมีตำแหน่งที่แตกต่างกันในการแปลที่แตกต่างกัน
howettl

5
พยายามที่จะเข้าใจว่ารหัสทำอะไรเมื่อมีข้อสงสัย int start คือตัวเลขที่คุณกำหนดซึ่งเป็นดัชนีเริ่มต้นของการขยาย ลอง 0 สำหรับการเริ่มต้นสตริง (). ขนาด () สำหรับจุดสิ้นสุด
wtsang02

86

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

ข้อที่สอง: คุณไม่จำเป็นต้องเขียนฟังก์ชั่นเสริมที่ตอบโดยw3bsharkเมื่อใช้ Kotlin

Finnaly: สิ่งที่คุณต้องทำคือใช้ไลบรารี Kotlin android-ktxจาก Google (ดูที่นี่เพื่อค้นหาข้อมูลเพิ่มเติมและวิธีรวมไว้ในโครงการของคุณ):

// Suppose id = 1111 and name = neil (just what you want). 
val s = SpannableStringBuilder()
          .bold { append(id) } 
          .append(name)
txtResult.setText(s) 

ผลิต: 1111นีล


UPDATE:

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

  • เมื่อคุณต้องการแสดงข้อความที่มีบางส่วนเป็นสีน้ำเงินและตัวเอียง:

    val myCustomizedString = SpannableStringBuilder()
        .color(blueColor, { append("A blue text ") })
        .append("showing that ")
        .italic{ append("it is painless") }
  • เมื่อคุณต้องการแสดงข้อความทั้งตัวหนาและตัวเอียง:

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

ในระยะสั้นbold, append, colorและฟังก์ชั่นส่วนขยายไปยังitalic SpannableStringBuilderคุณสามารถดูฟังก์ชั่นเสริมอื่น ๆ ในเอกสารประกอบอย่างเป็นทางการจากที่ที่คุณสามารถคิดความเป็นไปได้อื่น ๆ


นี่มันยอดเยี่ยมและทั้งหมด แต่ฉันคิดว่าทุกคำตอบที่เกี่ยวข้องกับสตริงควรพิจารณาการแปล คำในประโยคสามารถเรียงลำดับและจัดโครงสร้างแตกต่างกันโดยสิ้นเชิงในบางภาษาดังนั้นการผนวกเช่นนี้อาจไม่สามารถใช้ได้ในบางสถานการณ์ ยังไม่เหมาะสำหรับสิ่งต่างๆเช่นสตริงปริมาณใน XML
Edward van

1
@CoolMind ไม่ทำให้คุณไม่สามารถใช้ Android KTX ได้ คุณสามารถค้นหาข้อมูลจาก github.com/android/android-ktx เกี่ยวกับวิธีการรายงานข้อผิดพลาดให้คำแนะนำคุณสมบัติหรือมีส่วนร่วมในห้องสมุดที่ ดังนั้นมันยังคงเป็นข้อมูลอ้างอิงที่ถูกต้อง ฉันได้อัปเดตคำตอบเพื่อรวมข้อมูลเพิ่มเติมเกี่ยวกับห้องสมุดและวิธีใช้งานในโครงการของคุณ
Filipe Brito

1
มอบเหรียญสำหรับผู้ชายคนนี้ให้กับโซลูชั่นและทรัพยากรที่ทันสมัยนี้ !! ขอบคุณ !!!
Sjd

37

ฉันคิดว่าคำตอบที่เลือกไม่ได้ให้ผลลัพธ์ที่น่าพอใจ ฉันได้เขียนฟังก์ชั่นของตัวเองซึ่งใช้ 2 สาย; ข้อความแบบเต็มและส่วนของข้อความที่คุณต้องการทำให้เป็นตัวหนา

มันคืน SpannableStringBuilder ด้วย 'textToBold' จาก 'text' เป็นตัวหนา

ฉันค้นหาความสามารถในการสร้างซับสตริงตัวหนาโดยไม่ต้องห่อในแท็กที่มีประโยชน์

    /**
     * Makes a substring of a string bold.
     * @param text          Full text
     * @param textToBold    Text you want to make bold
     * @return              String with bold substring
     */

    public static SpannableStringBuilder makeSectionOfTextBold(String text, String textToBold){

        SpannableStringBuilder builder=new SpannableStringBuilder();

        if(textToBold.length() > 0 && !textToBold.trim().equals("")){

            //for counting start/end indexes
            String testText = text.toLowerCase(Locale.US);
            String testTextToBold = textToBold.toLowerCase(Locale.US);
            int startingIndex = testText.indexOf(testTextToBold);
            int endingIndex = startingIndex + testTextToBold.length();
            //for counting start/end indexes

            if(startingIndex < 0 || endingIndex <0){
                return builder.append(text);
            }
            else if(startingIndex >= 0 && endingIndex >=0){

                builder.append(text);
                builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
            }
        }else{
            return builder.append(text);
        }

        return builder;
  }

คุณสามารถให้ตัวอย่างของวิธีการใช้ในรหัสได้หรือไม่?
Micro

2
@MicroR คุณจะต้องผ่านสองสายสตริงที่สองจะต้องเป็นส่วนของข้อความที่อยู่ภายในครั้งแรก เช่น makeSectionOfTextBold ("นี่คือข้อความที่ยอดเยี่ยม", "ดีมาก")
Leon

1
คุณควรเปลี่ยนคำสั่ง if ด้วย if (textToBold! = null &&! textToBold.isEmpty ())
Arda Kara

2
ฟังก์ชันนี้ไม่คาดว่า substring สามารถเกิดขึ้นได้ในข้อความเต็มหลายครั้ง ตัวอย่างเช่นใน "ชื่อผู้ใช้ของฉันคือชื่อ" มันไม่สามารถทำให้ตัวหนา "ชื่อ" ที่ 2
Jadamec

1
ดังนั้นเมธอดนี้ควรมีชื่อว่า makeAllBold (text, textToBold)
wtsang02

30

ตามที่ wtsang02 กล่าวว่าการใช้ HTML เป็นค่าใช้จ่ายที่มีราคาแพง เพียงใช้วิธีแก้ปัญหาเนทิฟ หากคุณไม่ต้องแก้ไขสตริงให้ใช้ SpannableString ไม่ใช่ SpannableStringBuilder

String boldText = "id";
String normalText = "name";
SpannableString str = new SpannableString(boldText + normalText);
str.setSpan(new StyleSpan(Typeface.BOLD), 0, boldText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(str);

23

ในกรณีที่คุณต้องการใช้สตริงจาก XML คุณสามารถทำสิ่งนี้:

strings.xml (ส่วน "CDATA" มีความสำคัญมิฉะนั้นจะใช้งานไม่ได้)

<string name="test">
     <![CDATA[
 <b>bold!</b> normal
    ]]>
</string>

จัดวางไฟล์

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_gravity="center" />

</FrameLayout>

รหัส

textView.text = HtmlCompat.fromHtml(getString(R.string.test), HtmlCompat.FROM_HTML_MODE_LEGACY)

<string name="test"><b>text bold</b> other text</string>งานนี้สำหรับฉัน ไม่ทำงานถ้าฉันเขียน<![CDATA[
sara

@sara ทดสอบอีกครั้งในวันที่ Pixel 2 กับ Q. ใช้งานได้ดี ที่นี่ฉันได้รับการปรับปรุงวิธีการทำงานกับ Kotlin กรุณาลองอีกครั้ง.
นักพัฒนา android

นี่คือคำตอบที่ยอมรับได้หากคุณใช้แบบอักษรที่กำหนดเอง Kudus เพื่อ Creater
Raghul Sugathan

12

มันง่ายเพียงแค่ปิดข้อความที่ระบุเช่นนี้ <b>"your text here:"</b>

<string name="headquarters">"<b>"Headquarters:"</b>" Mooresville, North Carolina, U.S.</string>

ผลลัพธ์: สำนักงานใหญ่: Mooresville, North Carolina, US


ใช้งานได้ก็ต่อเมื่อใช้สตริงจาก xml หากสตริงนี้ถูกเรียกใช้โดยทางโปรแกรมการเข้ารหัส html จะถูกถอดออก
Starwave

11

หากคุณกำลังใช้ Kotlin การทำเช่นนั้นจะง่ายขึ้นโดยใช้core-ktxเนื่องจากมีภาษาเฉพาะโดเมน (DSL)สำหรับการทำสิ่งนี้:

val string: SpannedString = buildSpannedString {
    bold {
        append("foo")
    }
    append("bar")     
}

ตัวเลือกเพิ่มเติมโดย:

append("Hello There")
bold {
    append("bold")
    italic {
        append("bold and italic")
        underline {
            append("then some text with underline")
        }
    }
}

ในที่สุดคุณสามารถ:

textView.text = string

10

นี่เป็นทางออกที่ดีกว่าถ้าคุณต้องการทำให้หลาย ๆ ข้อความเป็นตัวหนา ฉันปรับปรุงรหัสของ Eitan แล้ว ขอบคุณ Eitan

public static SpannableStringBuilder makeSectionOfTextBold(String text, String... textToBold) {
    SpannableStringBuilder builder = new SpannableStringBuilder(text);

    for (String textItem :
            textToBold) {
        if (textItem.length() > 0 && !textItem.trim().equals("")) {
            //for counting start/end indexes
            String testText = text.toLowerCase(Locale.US);
            String testTextToBold = textItem.toLowerCase(Locale.US);
            int startingIndex = testText.indexOf(testTextToBold);
            int endingIndex = startingIndex + testTextToBold.length();

            if (startingIndex >= 0 && endingIndex >= 0) {
                builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
            }
        }
    }

    return builder;
}

8

จากคำตอบของ @ mladj0ni ฉันได้รับโค้ดด้านล่างเพื่อใช้งาน ปัญหาคือว่าถ้าคุณใช้String.formatมันจะตัดมาร์กอัป html ออกดังนั้นคุณต้องหลีกเลี่ยงสัญลักษณ์วงเล็บเหลี่ยมใน strings.xml:

strings.xml:

<string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>

code.java:

String unspanned = String.format(Locale.US, "%s%s", getResources().getString(R.string. welcome_messages), 99);

Spanned spanned;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
    spanned = Html.fromHtml(unspanned, Html.FROM_HTML_MODE_LEGACY);
} else {
    spanned = Html.fromHtml(unspanned);
}

textView.setText(spanned);

มันง่ายกว่า SpannableStringBuilder สำหรับประสิทธิภาพหากคุณแสดงเพียงหนึ่งสตริงผู้ใช้จะไม่สังเกตเห็นมิลลิวินาทีพิเศษเพื่อแยกวิเคราะห์

โปรดดูเอกสารที่นี่


ขอบคุณสำหรับ & lt; b> ... & lt; / b>
ออกเมื่อ

4

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

String myText = "make this <b>bold</b> and <b>this</b> too";
textView.setText(makeSpannable(myText, "<b>(.+?)</b>", "<b>", "</b>"));

public SpannableStringBuilder makeSpannable(String text, String regex, String startTag, String endTag) {

            StringBuffer sb = new StringBuffer();
            SpannableStringBuilder spannable = new SpannableStringBuilder();

            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(text);
            while (matcher.find()) {
                sb.setLength(0);
                String group = matcher.group();
                String spanText = group.substring(startTag.length(), group.length() - endTag.length());
                matcher.appendReplacement(sb, spanText);

                spannable.append(sb.toString());
                int start = spannable.length() - spanText.length();

                spannable.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), start, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            sb.setLength(0);
            matcher.appendTail(sb);
            spannable.append(sb.toString());
            return spannable;
        }

3
public static Spanned getBoldString(String textNotBoldFirst, String textToBold, String textNotBoldLast) {
    String resultant = null;

    resultant = textNotBoldFirst + " " + "<b>" + textToBold + "</b>" + " " + textNotBoldLast;

    return Html.fromHtml(resultant);

}

ลองสิ่งนี้ มันสามารถช่วยได้อย่างแน่นอน


3

ทำให้ char แรกของสตริงที่ spannable ขณะค้นหา char ใน list / recycler like

r a vi และ ajay

ก่อนหน้าไฮไลต์แบบนี้ แต่ฉันอยากจะเป็นด้านล่าง

ravi a nd ajay หรือ ravi และa jay

สำหรับสิ่งนี้ฉันค้นหาความยาวของคำหากมันเท่ากับ 1 ฉันแยกสตริงหลักออกเป็นคำและคำนวณตำแหน่งเริ่มต้นของคำจากนั้นฉันค้นหาคำที่ขึ้นต้นด้วย char

 public static SpannableString colorString(int color, String text, String... wordsToColor) {
    SpannableString coloredString = new SpannableString(text);

    for (String word : wordsToColor) {

        Log.e("tokentoken", "-wrd len-" + word.length());
        if (word.length() !=1) {
            int startColorIndex = text.toLowerCase().indexOf(word.toLowerCase());
            int endColorIndex = startColorIndex + word.length();
            try {
                coloredString.setSpan(new ForegroundColorSpan(color), startColorIndex, endColorIndex,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            } catch (Exception e) {
                e.getMessage();
            }
        } else {
            int start = 0;

            for (String token : text.split("[\u00A0 \n]")) {
                if (token.length() > 0) {
                    start = text.indexOf(token, start);
                   // Log.e("tokentoken", "-token-" + token + "   --start--" + start);
                    char x = token.toLowerCase().charAt(0);
                    char w = word.toLowerCase().charAt(0);
                   // Log.e("tokentoken", "-w-" + w + "   --x--" + x);

                    if (x == w) {
                        // int startColorIndex = text.toLowerCase().indexOf(word.toLowerCase());
                        int endColorIndex = start + word.length();
                        try {
                            coloredString.setSpan(new ForegroundColorSpan(color), start, endColorIndex,
                                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

                        } catch (Exception e) {
                            e.getMessage();
                        }
                    }
                }
            }

        }

    }

    return coloredString;
}

3

ฉันมาที่นี่เพื่อมอบโซลูชันที่เป็นปัจจุบันมากขึ้นเพราะฉันไม่พอใจกับคำตอบที่มีอยู่ Html.fromHtml()ผมจำเป็นต้องมีอะไรบางอย่างที่จะทำงานให้ตำราแปลและไม่ได้มีการตีประสิทธิภาพของการใช้ หากคุณกำลังใช้ Kotlin นี่คือฟังก์ชั่นการขยายซึ่งจะตั้งค่าได้ง่ายหลายส่วนของข้อความของคุณไปเป็นตัวหนา สิ่งนี้ใช้ได้เช่นเดียวกับ Markdown และสามารถขยายเพื่อรองรับแท็ก Markdown อื่น ๆ หากจำเป็น

val yourString = "**This** is your **string**.".makePartialTextsBold()
val anotherString = getString(R.string.something).makePartialTextsBold()

/**
 * This function requires that the parts of the string that need
 * to be bolded are wrapped in ** and ** tags
 */
fun String.makePartialTextsBold(): SpannableStringBuilder {
    var copy = this
    return SpannableStringBuilder().apply {
        var setSpan = true
        var next: String
        do {
            setSpan = !setSpan
            next = if (length == 0) copy.substringBefore("**", "") else copy.substringBefore("**")
            val start = length
            append(next)
            if (setSpan) {
                setSpan(StyleSpan(Typeface.BOLD), start, length,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            copy = copy.removePrefix(next).removePrefix("**")
        } while (copy.isNotEmpty())
    }
}

3

wtsang02คำตอบเป็นวิธีที่ดีที่สุดที่จะไปเกี่ยวกับเรื่องนี้ตั้งแต่ Html.fromHtml ("") เลิกใช้แล้ว ที่นี่ฉันจะเพิ่มประสิทธิภาพเล็กน้อยสำหรับใครก็ตามที่มีปัญหาในการทำให้คำแรกเป็นตัวหนาแบบไดนามิกไม่ว่าขนาดของประโยคจะเป็นเท่าใด

แรกให้สร้างวิธีการรับคำแรก:

 private String getFirstWord(String input){

    for(int i = 0; i < input.length(); i++){

        if(input.charAt(i) == ' '){

            return input.substring(0, i);
        }
    }

    return input;
}

สมมติว่าคุณมีสายยาวเช่นนี้:

String sentence = "friendsAwesomeName@gmail.com want's to be your friend!"

และคุณต้องการประโยคของคุณให้เป็นyourAwesomeName@gmail.comต้องการเป็นเพื่อนของคุณ! สิ่งที่คุณต้องทำคือ - รับคำแรกและรับความยาวของมันเพื่อทำให้คำแรกเป็นตัวหนาสิ่งนี้:

String myFirstWord = getFirstWord(sentence);
int start = 0; // bold will start at index 0
int end = myFirstWord.length(); // and will finish at whatever the length of your first word

ตอนนี้เพียงทำตามขั้นตอนของ wtsang02เช่นนี้:

SpannableStringBuilder fancySentence = new SpannableStringBuilder(sentence);
fancySentence.setSpan(new android.text.style.StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(fancySentence);

และนั่นมัน! ตอนนี้คุณน่าจะสามารถใช้ตัวหนากับขนาดใดก็ได้จากประโยคยาว / สั้น หวังว่ามันจะช่วยให้ใครบางคนมีความสุขการเข้ารหัส :)


3

นี่คือฟังก์ชั่นเสริม Kotlin ที่ฉันใช้สำหรับสิ่งนี้

/**
 * Sets the specified Typeface Style on the first instance of the specified substring(s)
 * @param one or more [Pair] of [String] and [Typeface] style (e.g. BOLD, ITALIC, etc.)
 */
fun TextView.setSubstringTypeface(vararg textsToStyle: Pair<String, Int>) {
    val spannableString = SpannableString(this.text)
    for (textToStyle in textsToStyle) {
        val startIndex = this.text.toString().indexOf(textToStyle.first)
        val endIndex = startIndex + textToStyle.first.length

        if (startIndex >= 0) {
            spannableString.setSpan(
                StyleSpan(textToStyle.second),
                startIndex,
                endIndex,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
            )
        }
    }
    this.setText(spannableString, TextView.BufferType.SPANNABLE)
}

การใช้งาน:

text_view.text="something bold"
text_view.setSubstringTypeface(
    Pair(
        "something bold",
        Typeface.BOLD
    )
)

.

text_view.text="something bold something italic"
text_view.setSubstringTypeface(
    Pair(
        "something bold ",
        Typeface.BOLD
    ),
    Pair(
        "something italic",
        Typeface.ITALIC
    )
)

2

คุณสามารถเพิ่มทั้งสองสายแยกกันในตัวสร้างหนึ่งในนั้นคือ springString ส่วนอีกสตริงหนึ่งเป็นปกติวิธีนี้คุณไม่จำเป็นต้องคำนวณดัชนี

val instructionPress = resources?.getString(R.string.settings_press)

val okText = resources?.getString(R.string.ok)
val spannableString = SpannableString(okText)

val spannableBuilder = SpannableStringBuilder()
spannableBuilder.append(instructionPress)
spannableBuilder.append(spannableString, StyleSpan(Typeface.BOLD), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

instructionText.setText(spannableBuilder,TextView.BufferType.SPANNABLE)

2

หากตำแหน่งของข้อความตัวหนาได้รับการแก้ไข (เช่น: ถ้าเป็นตอนเริ่มต้นของ textView) ให้ใช้ textView สองแบบที่ต่างกันพร้อมพื้นหลังเดียวกัน จากนั้นคุณสามารถทำให้ textView ของ textStyle อื่นเป็นตัวหนา

นี้จะต้องมีหน่วยความจำสองเท่าเมื่อเทียบกับ textView เดียว แต่ความเร็วจะเพิ่มขึ้น


1

ฉันได้สร้างวิธีการคงที่สำหรับการตั้งค่าส่วนหนึ่งของข้อความตัวหนาสำหรับ TextView และ EditText

public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex){
        if(!contentData.isEmpty() && contentData.length() > endIndex) {
            final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);

            final StyleSpan bss = new StyleSpan(Typeface.BOLD); // Span to make text bold
            final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text normal
            sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
            sb.setSpan(iss,endIndex, contentData.length()-1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            if(mView instanceof TextView)
               ((TextView) mView).setText(sb);
            else if(mView instanceof EditText)
               ((EditText) mView).setText(sb);

        }
    }

รหัสอื่นที่กำหนดเองเพิ่มเติม

  /*typeFaceStyle can be passed as 

    Typeface.NORMAL = 0;
    Typeface.BOLD = 1;
    Typeface.ITALIC = 2;
    Typeface.BOLD_ITALIC = 3;*/

    public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex,int typeFaceStyle){
        if(!contentData.isEmpty() && contentData.length() > endIndex) {
            final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);

            final StyleSpan bss = new StyleSpan(typeFaceStyle); // Span to make text bold
            final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text italic
            sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
            sb.setSpan(iss,endIndex,contentData.length()-1,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            if(mView instanceof TextView)
                ((TextView) mView).setText(sb);
            else if(mView instanceof EditText)
                ((EditText) mView).setText(sb);
        }
    }

1

ในกรณีที่มีผู้ใช้ Data Binding เราสามารถกำหนดอะแดปเตอร์ผูกพันเช่นนี้

@BindingAdapter("html")
fun setHtml(view: TextView, html: String) {
    view.setText(HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY))
}

จากนั้นเราสามารถใช้มันกับ TextView

app:html="@{@string/bold_text}"

โดยที่ bold_text คือ

<string name="bold_text"><![CDATA[Part of text is <b>bold</b>]]></string>

คุณเขียนฟังก์ชัน "setHtml" ที่ไหน
นักพัฒนา Android


โอ้นี่มันแปลกสำหรับฉัน ขอบคุณ. คุณรู้ไหมว่าอาจเป็นแบบฝึกหัด / ตัวอย่างที่ดีสำหรับผู้มาใหม่ในหัวข้อนี้?
นักพัฒนา Android

ฉันไม่รู้บทเรียน เพียงแค่ google "android BindingAdapter"
logcat

1

ค้นพบวิธีการในกรณีที่คุณต้องการจัดการการแปลหลายภาษาในหลาย ๆ ภาษามันน่าเบื่อที่จะทำ แต่มันใช้งานได้สมมติว่าเราต้องการสิ่งนี้:

เป็นภาษาอังกฤษ:

ไม่มีการลงทะเบียนการชำระเงิน

ในภาษาสเปน:

ไม่มีการลงทะเบียนhay pagos

คุณต้องสร้าง 3 สาย

ภาษาอังกฤษ:

<string name="start_string">There are no</string>
<string name="middle_string">payments</string>
<string name="end_string">registered.</string>
<string name="string_format" translatable="false">%1$s %2$s %3$s</string>

สเปน:

<string name="start_string">No hay</string>
<string name="middle_string">pagos</string>
<string name="end_string">registrados</string>

ตอนนี้คุณสามารถทำได้:

val startSpanPosition = getString(R.string.start_string).length
val endSpanPosition = startSpanPosition + getString(R.string.middle_string).length
val mySpannableString = SpannableStringBuilder(String.format(getString(R.string.string_format),
        getString(R.string.start_string), getString(R.string.middle_string))), getString(R.string.end_string)))

mySpannableString.setSpan(StyleSpan(Typeface.BOLD), spanStartPosition, endSpanPosition, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

1

ทรัพยากร String ของคุณ

<resources>
   <string name="your_string_resource_name">This is normal text<![CDATA[<b> but this is bold </b>]]> and <![CDATA[<u> but this is underline text</u>]]></string>
</resources> 

คลาส java ของคุณ

yourtextView.setText(getString(R.string.your_string_resource_name));

0

นี่คือโซลูชันที่สมบูรณ์ของฉันสำหรับค่าสตริงแบบไดนามิกด้วยการตรวจสอบเคส

/**
 * Makes a portion of String formatted in BOLD.
 *
 * @param completeString       String from which a portion needs to be extracted and formatted.<br> eg. I am BOLD.
 * @param targetStringToFormat Target String value to format. <br>eg. BOLD
 * @param matchCase Match by target character case or not. If true, BOLD != bold
 * @return A string with a portion formatted in BOLD. <br> I am <b>BOLD</b>.
 */
public static SpannableStringBuilder formatAStringPortionInBold(String completeString, String targetStringToFormat, boolean matchCase) {
    //Null complete string return empty
    if (TextUtils.isEmpty(completeString)) {
        return new SpannableStringBuilder("");
    }

    SpannableStringBuilder str = new SpannableStringBuilder(completeString);
    int start_index = 0;

    //if matchCase is true, match exact string
    if (matchCase) {
        if (TextUtils.isEmpty(targetStringToFormat) || !completeString.contains(targetStringToFormat)) {
            return str;
        }

        start_index = str.toString().indexOf(targetStringToFormat);
    } else {
        //else find in lower cases
        if (TextUtils.isEmpty(targetStringToFormat) || !completeString.toLowerCase().contains(targetStringToFormat.toLowerCase())) {
            return str;
        }

        start_index = str.toString().toLowerCase().indexOf(targetStringToFormat.toLowerCase());
    }

    int end_index = start_index + targetStringToFormat.length();
    str.setSpan(new StyleSpan(BOLD), start_index, end_index, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return str;
}

เช่น. completeString = "ฉันเป็นตัวหนา"

กรณีฉัน ถ้า*targetStringToFormat* = "bold"และ*matchCase* = true

ส่งกลับ "I BOLD" (เนื่องจากเป็นตัวหนา! = BOLD)

กรณีที่สอง ถ้า*targetStringToFormat* = "bold"และ*matchCase* = false

ส่งคืน "ฉันเป็นตัวหนา "

เพื่อนำไปใช้:

myTextView.setText(formatAStringPortionInBold("I am BOLD", "bold", false))

หวังว่าจะช่วย!

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