如何使一个特定的文本TextView粗体

我不知道如何使TextView上的特定文本变成粗体。

是这样的

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

我希望输出是这样的:

1111尼尔

idname是我从数据库中检索值的变量,我想将id改为粗体,但只有id,所以name不会受到影响,我不知道如何做到这一点。

287324 次浏览

只需要在HTML中构建字符串并设置它:

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

虽然你可以使用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);

我认为所选择的答案并没有提供一个令人满意的结果。我写了自己的函数,它有两个字符串;全文和要加粗的文本部分。

它返回一个SpannableStringBuilder,带有从'text'中粗体的'textToBold'。

我发现使子字符串加粗而不用标签包装的能力很有用。

    /**
* 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;
}
public static Spanned getBoldString(String textNotBoldFirst, String textToBold, String textNotBoldLast) {
String resultant = null;


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


return Html.fromHtml(resultant);


}

试试这个。这绝对有帮助

这里有一个更好的解决方案,如果你想使多个文本粗体。我改进了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;
}

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

如果你想使用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)

我已经为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);
}
}

根据@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简单。至于性能,如果只显示一个字符串,那么用户不会注意到解析它所花费的额外毫秒。

参见文档在这里

它很简单,像这样关闭指定的文本,例如<b>"your text here:"</b>

<string name="headquarters">"<b>"Headquarters:"</b>" Mooresville, North Carolina, U.S.</string>
< p >结果: 总部:美国北卡罗来纳州穆尔斯维尔

当在list/recycler中搜索char时,使字符串的第一个char可扩展

r一个vi和ajay

以前突出显示像这样,但我想像下面

ravi 一个nd ajay ravi和一个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;
}
我来这里是为了提供一个最新的解决方案,因为我对现有的答案不满意。 我需要一些东西,将工作于翻译文本,并没有使用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())
}
}

首先:你不需要担心使用Raghav Sood的回答是中缓慢的性能代码。

第二:使用Kotlin时,不需要编写w3bshark的回答提供的扩展函数。

最后:所有你需要做的就是从谷歌使用Kotlin android-ktx图书馆(参考在这里找到更多信息以及如何在你的项目中包含它):

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

产生:1111 neil


更新:

因为我认为它可以帮助其他人,也可以展示你可以走多远,这里有更多的用例。

  • 当你需要用蓝色和斜体显示文本部分时:

    val myCustomizedString = SpannableStringBuilder()
    .color(blueColor, { append("A blue text ") })
    .append("showing that ")
    .italic{ append("it is painless") }
    
  • When you need to display a text in both bold and italic:

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

In short, bold, append, color and italic are extension functions to SpannableStringBuilder. You can see another extension functions in the official documentation, from where you can think for other possibilities.

您可以在构建器中分别添加这两个字符串,其中一个是spannedString,另一个是常规字符串。这样就不需要计算下标了。

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)

这是我的完整的解决方案,动态字符串值与大小写检查。

/**
* 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 = "I am BOLD"
.

< >强情况下我 if *targetStringToFormat* = "bold" and *matchCase* = true

返回“I am BOLD”(因为BOLD != BOLD)

< >强二世 if *targetStringToFormat* = "bold" and *matchCase* = false

返回“I am 大胆的

应用:

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

希望有帮助!

如果粗体文本的位置是固定的(例如:如果是在textView的开始),然后使用两个不同的textView具有相同的背景。然后你可以使其他textView的textStyle为粗体。

与单个textView相比,这将需要两倍的内存,但速度会提高。

您可以使用此代码将部分文本设置为粗体。对于粗体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;
}

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想要成为你的朋友! 你所要做的就是-获取firstWord并获取它的长度以使firstWord加粗,就像这样:

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

就是这样!现在你应该可以在长句或短句中加粗任意大小的单词了。

这是我使用的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
)
)

如果你正在使用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

以防有人使用数据绑定。我们可以像这样定义绑定适配器

@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>

找到了一种方法,如果你想处理多种语言的本地化,这很无聊,但它是有效的,让我们假设我们想要这样:

英文:

没有注册支付

西班牙语:

没有干草帕果-帕果注册人

你必须创建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)

字符串资源

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

简单的例子

在you strings.xml中

<string name="str_privacy_policy">This is our Privacy Policy.</string>

如果你想要制定明确的“隐私政策”;As bold将字符串放在粗体标记之间。

像这样

<string name="str_privacy_policy">This is our <b>Privacy Policy.</b></string>

结果是

这是我们的隐私政策

我用这个代码来加粗特定的单词…

    Spanned string = Html.fromHtml("Normal string <b>BOLD STRING</b>");
textView.setText(string);

只需在标签中添加这个

dangerouslySetInnerHTML=\{\{__html: "<p>Your html text here.<p>"}}

下面是我如何使用正则表达式和Kotlin来做到这一点

val BOLD_SPAN = StyleSpan(Typeface.BOLD)


fun TextView.boldMatches(regexString: String) {
this.applyStyleSpanToMatches(regexString, BOLD_SPAN)
}
    



fun TextView.applyStyleSpanToMatches(regexString: String, span: StyleSpan){
this.text = this.text.toString().applyStyleSpanToMatches(regexString, span)
}


fun String.applyStyleSpanToMatches(regexString: String, span: StyleSpan): Spannable {
val result = SpannableString.valueOf(this)
if(regexString.isEmpty()) return result
val pattern = try{
Pattern.compile(regexString)
} catch (e: PatternSyntaxException){
return result
}
val matcher = pattern.matcher(result)
while (matcher.find()) {
val start = matcher.start()
val end = matcher.end()
result.setSpan(span, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
return result
}

使用问题 它可以这样应用:

txtResult.boldMatches(id)

这不是最简单的解决方案吗?

<string name="string">Please provide your <b>Name</b> properly</string>

只要使用你想要的字符串:)

结果如下所示:

请正确提供您的的名字