SpannableStringBuilder创建具有多种字体/文本大小等的String示例?


Answers:


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

1
另外,如何设置字体大小(例如粗体)?所以我同时指定它是粗体并说字体20?
代码Droid 2012年

7
另外,请将索引更新为(finalString.indexOf(normalBOLD),finalString.indexOf(normalBOLD)+ normalBOLD.lenth())
代码Droid

2
况且什么CodeDroid说,另一个问题是,IndexOf方法可以捕捉重复单词,并留下您end的前start一个IndexOutOfBoundsException。因此,最好格式化子字符串,然后将它们放在一起。
Noumenon

@hotveryspicy我怀疑“ finalString.indexOf(normalBOLD)”这部分-与外观相反-由于String interning而有效-是吗?
Paul Brewczynski 2014年

注意:android:textAllCaps="true"将打破SpannableString
某处某人

78

接受的答案很好(我赞成),但是它无法按照提交者的要求使用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");

2
另外,通过在附加文本之前检索文本的粗体部分的开始位置,您不必担心本应为粗体的单词重复出现。
Qw4z1

52

如果您使用的是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颜色在哪里。

甚至有可能嵌套跨度,因此您最终会获得嵌入式DSL:

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

您需要在您的应用程序模块级别中执行以下操作build.gradle

repositories {
    google()
}

dependencies {
    implementation "androidx.core:core-ktx:1.2.0"
}

2
如果可以使用Kotlin,绝对是最好的选择。DSL使它成为一个更好得多的API。
Baptiste Candellier

1
它如何与LiveData <String>一起使用?即使一切正在编译并且看起来还可以,我似乎无法使其应用这些更改。
遵守

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

7

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

Spanned styledText = Html.fromHtml("First Part Not Bold <b>BOLD</b> rest not bold");
textView.setText(styledText);

19
请记住,这确实很慢,如果在滚动过程中完成,可能会导致跳过帧。
Phil Kulak

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

希望能帮助到你。


完美的答案,您拯救了我的一天!我已经用val p = Pattern.compile(“ <b>([^^] *)</ b>”,Pattern.MULTILINE或Pattern.DOTALL)替换了模式,因为如果您只有开始标签all文本为粗体。谢谢
AndroidRuntimeException

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。


3

我们还可以将SpannableStringBuilderTextAppearanceSpan结合使用来实现。请按照以下步骤实施。

  1. 在中创建样式styles.xml

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

  1. 使用下面的代码。
SpannableStringBuilder builder = new SpannableStringBuilder(“第一部分不加粗,其余部分不加粗”);
builder.setSpan(new TextAppearanceSpan(this,R.style.BoldStyle),20,24,0);
((TextView)findViewById(R.id.tv7))。setText(builder);

而已。希望对别人有帮助。


1

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

SpannableString ss = SpannableBuilder.init("First Part Not Bold BOLD rest not bold")
                                     .makeBold("BOLD")
                                     .create()

4
因为spannablebuilder会建立一个跨度,而spannablestringbuilder是用于建立具有多个不同跨度的
字符序列
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.