如何在运行时在android中使部分文本加粗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10979821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:39:02  来源:igfitidea点击:

How to make part of the text Bold in android at runtime?

androidandroid-listview

提问by Housefly

A ListViewin my application has many string elements like name, experience, date of joining, etc. I just want to make namebold. All the string elements will be in a single TextView.

一个ListView在我的应用程序有很多字符串元素,如nameexperiencedate of joining,等我只是想name大胆。所有字符串元素都将在一个TextView.

my XML:

我的 XML:

<ImageView
    android:id="@+id/logo"
    android:layout_width="55dp"
    android:layout_height="55dp"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="15dp" >
</ImageView>

<TextView
    android:id="@+id/label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/logo"
    android:padding="5dp"
    android:textSize="12dp" >
</TextView>

My code to set the TextView of the ListView item:

我设置 ListView 项的 TextView 的代码:

holder.text.setText(name + "\n" + expirience + " " + dateOfJoininf);

回答by Imran Rana

Say you have a TextViewcalled etx. You would then use the following code:

假设您有一个TextView电话etx。然后,您将使用以下代码:

final SpannableStringBuilder sb = new SpannableStringBuilder("HELLOO");

final StyleSpan bss = new StyleSpan(android.graphics.Typeface.BOLD); // Span to make text bold
final StyleSpan iss = new StyleSpan(android.graphics.Typeface.ITALIC); //Span to make text italic
sb.setSpan(bss, 0, 4, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold 
sb.setSpan(iss, 4, 6, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make last 2 characters Italic

etx.setText(sb);


回答by friederbluemle

Based on Imran Rana's answer, here is a generic, reusable method if you need to apply StyleSpans to several TextViews, with support for multiple languages (where indices are variable):

根据 Imran Rana 的回答,如果您需要将StyleSpans 应用于多个TextViews ,这里有一个通用的、可重用的方法,支持多种语言(其中索引是可变的):

void setTextWithSpan(TextView textView, String text, String spanText, StyleSpan style) {
    SpannableStringBuilder sb = new SpannableStringBuilder(text);
    int start = text.indexOf(spanText);
    int end = start + spanText.length();
    sb.setSpan(style, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    textView.setText(sb);
}

Use it in an Activitylike so:

Activity像这样使用它:

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ...

    StyleSpan boldStyle = new StyleSpan(Typeface.BOLD);
    setTextWithSpan((TextView) findViewById(R.id.welcome_text),
        getString(R.string.welcome_text),
        getString(R.string.welcome_text_bold),
        boldStyle);

    // ...
}


strings.xml

strings.xml

<string name="welcome_text">Welcome to CompanyName</string>
<string name="welcome_text_bold">CompanyName</string>


Result:

结果:

Welcome to CompanyName

欢迎使用公司名称

回答by copolii

The answers provided here are correct, but can't be called in a loop because the StyleSpanobject is a single contiguous span (not a style that can be applied to multiple spans). Calling setSpanmultiple times with the same bold StyleSpanwould create one bold spanand just move it around in the parent span.

此处提供的答案是正确的,但不能在循环中调用,因为StyleSpan对象是单个连续跨度(不是可应用于多个跨度的样式)。setSpan使用相同的粗体多次调用StyleSpan将创建一个粗体跨度,并在父跨度中移动它。

In my case (displaying search results), I needed to make all instances of all the search keywords appear bold. This is what I did:

就我而言(显示搜索结果),我需要使所有搜索关键字的所有实例都显示为粗体。这就是我所做的:

private static SpannableStringBuilder emboldenKeywords(final String text,
                                                       final String[] searchKeywords) {
    // searching in the lower case text to make sure we catch all cases
    final String loweredMasterText = text.toLowerCase(Locale.ENGLISH);
    final SpannableStringBuilder span = new SpannableStringBuilder(text);

    // for each keyword
    for (final String keyword : searchKeywords) {
        // lower the keyword to catch both lower and upper case chars
        final String loweredKeyword = keyword.toLowerCase(Locale.ENGLISH);

        // start at the beginning of the master text
        int offset = 0;
        int start;
        final int len = keyword.length(); // let's calculate this outside the 'while'

        while ((start = loweredMasterText.indexOf(loweredKeyword, offset)) >= 0) {
            // make it bold
            span.setSpan(new StyleSpan(Typeface.BOLD), start, start+len, SPAN_INCLUSIVE_INCLUSIVE);
            // move your offset pointer 
            offset = start + len;
        }
    }

    // put it in your TextView and smoke it!
    return span;
}

Keep in mind that the code above isn't smart enough to skip double-bolding if one keyword is a substring of the other. For example, if you search for "Fish fi"inside "Fishes in the fisty Sea"it will make the "fish"bold once and then the "fi"portion. The good thing is that while inefficient and a bit undesirable, it won't have a visual drawback as your displayed result will still look like

请记住,如果一个关键字是另一个关键字的子字符串,则上面的代码不够聪明,无法跳过双粗。例如,如果你搜索“鱼网络连接”“在fisty海鱼”就会使“鱼”大胆一次,然后在“网络连接”部分。好消息是,虽然效率低下且有点不受欢迎,但它不会有视觉缺陷,因为您显示的结果仍然看起来像

Fishes in the fisty Sea

在ES网络猪圈海

回答by Dmitrii Leonov

You can do it using Kotlin and buildSpannedStringextension function from core-ktx

你可以使用 Kotlin 和buildSpannedString扩展函数来做到这一点core-ktx

 holder.textView.text = buildSpannedString {
        bold { append("$name\n") }
        append("$experience $dateOfJoining")
 }

回答by Muhammed Refaat

if you don't know exactly the length of the text before the text portion that you want to make Bold, or even you don't know the length of the text to be Bold, you can easily use HTML tags like the following:

如果您不确切知道要加粗的文本部分之前的文本长度,或者甚至不知道要加粗的文本长度,则可以轻松使用如下 HTML 标记:

yourTextView.setText(Html.fromHtml("text before " + "<font><b>" + "text to be Bold" + "</b></font>" + " text after"));

回答by Isaias Carvalho

If you are using the @ srings / your_string annotation, access the strings.xml file and use the <b></b>tag in the part of the text you want.

如果您使用@srings/your_string 批注,请访问strings.xml 文件并<b></b>在您想要的文本部分使用标记。

Example:

例子:

    <string><b>Bold Text</b><i>italic</i>Normal Text</string>

回答by luky

Extending frieder's answer to support case and diacritics insensitivity.

扩展 Frieder 的答案以支持大小写和变音符号不敏感。

public static String stripDiacritics(String s) {
        s = Normalizer.normalize(s, Normalizer.Form.NFD);
        s = s.replaceAll("[\p{InCombiningDiacriticalMarks}]", "");
        return s;
}

public static void setTextWithSpan(TextView textView, String text, String spanText, StyleSpan style, boolean caseDiacriticsInsensitive) {
        SpannableStringBuilder sb = new SpannableStringBuilder(text);
        int start;
        if (caseDiacriticsInsensitive) {
            start = stripDiacritics(text).toLowerCase(Locale.US).indexOf(stripDiacritics(spanText).toLowerCase(Locale.US));
        } else {
            start = text.indexOf(spanText);
        }
        int end = start + spanText.length();
        if (start > -1)
            sb.setSpan(style, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        textView.setText(sb);
    }

回答by sonique

I recommend to use strings.xml file with CDATA

我建议使用带有 CDATA 的 strings.xml 文件

<string name="mystring"><![CDATA[ <b>Hello</b> <i>World</i> ]]></string>

Then in the java file :

然后在java文件中:

TextView myTextView = (TextView) this.findViewById(R.id.myTextView);
myTextView.setText(Html.fromHtml( getResources().getString(R.string.mystring) ));