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

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

我的 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:

holder.text.setText(name + "\n" + expirience + " " + dateOfJoininf);
79718 次浏览

Let's say you have a TextView called etx. You would then use the following code:

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

我建议对 CDATA 使用 strings.xml 文件

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

然后在 java 文件中:

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

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

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

像这样在 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

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

结果:

欢迎来到 CompanyName

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

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

请记住,如果一个关键字是另一个关键字的子字符串,则上面的代码不足以跳过双重加粗。例如,如果你在 “海里的鱼儿”中搜索 “ Fish Fi”,它将使 “鱼”加粗一次,然后是 “ Fi”部分。好的一面是,虽然效率低下,而且有点不受欢迎,但是它不会有视觉缺陷,因为显示的结果看起来仍然是这样

海里的鱼

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

如果你不知道粗体部分之前文本的长度,或者你甚至不知道粗体部分的文本长度,你可以很容易地使用 HTML 标签,如下所示:

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

你可以使用 Kotlin 和来自 core-ktxbuildSpannedString扩展功能

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

如果使用@sring/your _ string 注释,访问 strings.xml 文件并在所需的文本部分使用 <b></b>标记。

Example:

    <string><b>Bold Text</b><i>italic</i>Normal Text</string>
<string name="My_Name">Given name is <b>Not Right</b>Please try again </string>

在 string.xml 文件中使用“ b”标记。
也用于斜体“ i”和下划线“ u”。