91

我需要创建一个放置在 TextView 中的字符串,它将显示如下字符串:

第一部分不加粗 粗体 其余不加粗

所以我想知道如何使用它SpannableStringBuilder来做到这一点?

我可以使用三个 TextEdit 来完成此操作,但我想使用最佳解决方案。

4

11 回答 11

100
First Part Not Bold   BOLD  rest not bold

您可以按照@Rajesh 的建议或按此执行此操作。

String normalBefore= "First Part Not Bold ";
String normalBOLD=  "BOLD ";
String normalAfter= "rest not bold";
String finalString= normalBefore+normalBOLD+normalAfter;
Spannable sb = new SpannableString( finalString );
sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), finalString.indexOf(normalBOLD)+ normalBOLD.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //bold
sb.setSpan(new AbsoluteSizeSpan(intSize), finalString.indexOf(normalBOLD)+ normalBOLD.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);//resize size

在 TextView 中显示

textview.setText(sb,  TextView.BufferType.SPANNABLE);
于 2012-05-31T06:26:30.873 回答
93

接受的答案很好(我赞成),但它未能按照提交者的要求使用 SpannableStringBuilder。因为我有一个 Builder 最有意义的案例,这里是代码(如果这对其他人有帮助,还可以更改文本的颜色)。请注意,您还可以将初始字符串提供给 SpannableStringBuilder 构造函数,但我在此处将其设置为使用“附加”以明确您可以在所需的“粗体”文本之前附加很多内容,然后如图所示记录开始。我怀疑这也是比接受的答案更快的代码。

SpannableStringBuilder longDescription = new SpannableStringBuilder();
longDescription.append("First Part Not Bold ");
int start = longDescription.length();
longDescription.append("BOLD");
longDescription.setSpan(new ForegroundColorSpan(0xFFCC5500), start, longDescription.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
longDescription.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), start, longDescription.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
longDescription.append(" rest not bold");
于 2014-05-01T01:00:58.057 回答
84

如果您使用的是 Kotlin,您可以使用android-ktx库执行以下操作

val s = SpannableStringBuilder()
        .append("First Part Not Bold ")
        .bold { append("BOLD") } 
        .append("Rest not bold")

是 上的bold扩展功能SpannableStringBuilder您可以在此处查看文档以获取可以使用的操作列表。

另一个例子:

val s = SpannableStringBuilder()
            .color(green, { append("Green text ") })
            .append("Normal text ")
            .scale(0.5, { append("Text at half size " })
            .backgroundColor(green, { append("Background green") })

green解析的 RGB 颜色在哪里。

甚至可以嵌套 span,因此您最终会得到一个嵌入式 DSL:

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

您需要在您的应用程序模块级别build.gradle中使用以下内容才能使其工作:

repositories {
    google()
}

dependencies {
    implementation "androidx.core:core-ktx:1.2.0"
}
于 2018-04-27T01:04:08.447 回答
42

从 API 21 SpannableStringBuilder 包括一个简单的方法来做到这一点。这是一个解决方案示例:

SpannableStringBuilder builder= new SpannableStringBuilder();
StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD);
builder.append("First Part Not Bold ")
              .append("BOLD ", boldSpan, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
              .append("rest not bold");

由于您很有可能不支持 API 21,因此您只能从该方法复制代码:

public SpannableStringBuilder append(CharSequence text, Object what, int flags) {
        int start = length();
        append(text);
        setSpan(what, start, length(), flags);
        return this;
}
于 2016-03-21T13:07:53.797 回答
7

使用Html类在 TextView 中使用 HTML 代码:

Spanned styledText = Html.fromHtml("First Part Not Bold <b>BOLD</b> rest not bold");
textView.setText(styledText);
于 2012-05-31T06:20:50.293 回答
6

此代码应将 html 粗体标记内的所有内容设置为粗体。它还会删除标签,因此只显示里面的内容。

        SpannableStringBuilder sb = new SpannableStringBuilder("this is <b>bold</b> and this is <b>bold too</b>  and this is <b>bold too, again</b>.");

        Pattern p = Pattern.compile("<b>.*?</b>", Pattern.CASE_INSENSITIVE);            
        boolean stop = false;
        while (!stop)
        {
            Matcher m = p.matcher(sb.toString());
            if (m.find()) {
                sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                sb.delete(m.end()-4, m.end());
                sb.delete(m.start(), m.start() + 3);
            }
            else
                stop = true;
        }

这段代码也可以适配其他html风格的标签,比如Superscript(sup标签)等。

        SpannableStringBuilder sb = new SpannableStringBuilder("text has <sup>superscript</sup> tag");

        Pattern p = Pattern.compile("<sup>.*?</sup>", Pattern.CASE_INSENSITIVE);            
        boolean stop = false;
        while (!stop)
        {
            Matcher m = p.matcher(sb.toString());
            if (m.find()) {
                sb.setSpan(new SuperscriptSpan(), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                sb.delete(m.end()-6, m.end());
                sb.delete(m.start(), m.start() + 5);
            }
            else
                stop = true;
        }

要设置颜色,只需将 ForegroundColorSpan 与 setSpan 一起使用。

sb.setSpan(new ForegroundColorSpan(Color.rgb(255, 0, 0)), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

希望能帮助到你。

于 2015-08-05T20:35:30.103 回答
5

我们也可以使用SpannableStringBuilderTextAppearanceSpan来完成。请按照以下步骤来实现。

  1. 在 中创建样式styles.xml

<style name="BoldStyle">
   <!-- Can add other styling attributes -->
   <item name="android:textStyle">bold</item>
   ......
</style>

  1. 使用下面的代码。
SpannableStringBuilder builder = new SpannableStringBuilder("First Part Not Bold BOLD rest not bold");
builder.setSpan(new TextAppearanceSpan(this, R.style.BoldStyle), 20, 24, 0);
((TextView)findViewById(R.id.tv7)).setText(builder);

就是这样。希望它会帮助某人。

于 2017-06-18T08:12:30.307 回答
4

所以我知道这已经解决了,即使按照 SpannableStringBuilder 的要求,但如果你想更动态地构建一个字符串,我想我会提出这个问题。

// Stuff needed
TextView DataTextView = (TextView)rootView.findViewById(R.id.DataView);
String Fields[] = {...database column names as strings... "x","y"};

String DataString = new String();   

int start,stop;     // Start and Stop of formatting

// Final Result
SpannableStringBuilder coloredString = new SpannableStringBuilder(); 

SpannableString temp;       // Small segment of colored string
for (int i =0; i < Fields.length; i++)
{
    if (database_result.containsKey(Fields[i]))  // Be sure a field exists in the ContentValues
    {
            DataString = Fields[i]+": ";
        start = DataString.length();
        DataString = DataString+ +database_result.getAsInteger(Fields[i])+" ";
        stop= DataString.length();
        temp = new SpannableString(DataString);
        temp.setSpan(new ForegroundColorSpan(Color.WHITE),start, stop, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        coloredString.append(temp);
    }   
}
DataTextView.setText(coloredString);

database_result 是我从返回的 SQL 查询的 Cursor 类型构造的 ContentValues 类型。我遇到的唯一问题是起初它只是第一个部分的 ColorSpaning。每次您想在循环中使用一个(或任何其他类型的跨度)时,您都需要声明一个新的 ForegroundColorSpan 。

于 2014-12-24T12:54:01.657 回答
2

您可以在 kotlin 中加粗并调整字符串的一部分

val s = SpannableStringBuilder()
    .append("First Part Not Bold And No Resize ")
    .bold { scale(1.5f, { append("Second Part By Bold And Resize " )}) } 
    .append("Third Part Not Bold And No Resize")

yourTextview.text = s
于 2021-10-17T11:08:55.273 回答
1

既然可以使用 SpannableBuilder,为什么还要使用 SpannableStringBuilder?(https://gist.github.com/qtyq/90f9b4894069a8b3676c

SpannableString ss = SpannableBuilder.init("First Part Not Bold BOLD rest not bold")
                                     .makeBold("BOLD")
                                     .create()
于 2016-10-10T14:04:26.407 回答
0

对于Xamarin.Android

SpannableStringBuilder TextoFormateado = new SpannableStringBuilder();
                TextoFormateado.Append("Not Bold");
                int start = TextoFormateado.Length();

                TextoFormateado.Append("Bold and Red");
                TextoFormateado.SetSpan(new ForegroundColorSpan(new Color(255, 0, 0, 149)), 
                    start, TextoFormateado.Length(), SpanTypes.ExclusiveExclusive);
                TextoFormateado.SetSpan(new StyleSpan(TypefaceStyle.Bold), 
                    start, TextoFormateado.Length(), SpanTypes.ExclusiveExclusive);

                TextoFormateado.Append("Not bold");

                
                TxtFinalText.TextFormatted = TextoFormateado;
于 2021-03-04T01:12:32.830 回答