SpannableStringBuilder to create String with multiple fonts/text sizes etc Example?

后端 未结 9 1364
眼角桃花
眼角桃花 2020-11-28 03:00

I need to create a String placed in a TextView that will display a string like this:

First Part Not Bold BOLD rest not bold

相关标签:
9条回答
  • 2020-11-28 03:38

    Why would you use SpannableStringBuilder when you can use SpannableBuilder?? (https://gist.github.com/qtyq/90f9b4894069a8b3676c)

    SpannableString ss = SpannableBuilder.init("First Part Not Bold BOLD rest not bold")
                                         .makeBold("BOLD")
                                         .create()
    
    0 讨论(0)
  • 2020-11-28 03:43

    Use HTML code in TextView using the Html class:

    Spanned styledText = Html.fromHtml("First Part Not Bold <b>BOLD</b> rest not bold");
    textView.setText(styledText);
    
    0 讨论(0)
  • 2020-11-28 03:46

    From API 21 SpannableStringBuilder includes a simple method to do this. Here is a solution example:

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

    Since it is a good chance you do not support API 21 only you can duplicate the code from that method:

    public SpannableStringBuilder append(CharSequence text, Object what, int flags) {
            int start = length();
            append(text);
            setSpan(what, start, length(), flags);
            return this;
    }
    
    0 讨论(0)
  • 2020-11-28 03:48

    This code should set to bold everything that comes inside the html bold tag. And it also deletes the tag so only the content inside is displayed.

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

    This code can also be adapted for other html style tags, such as Superscript (sup tag), etc.

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

    To set the color, just use the ForegroundColorSpan with setSpan.

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

    Hope it helps.

    0 讨论(0)
  • 2020-11-28 03:49

    If you are using Kotlin you can do the following using the android-ktx library

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

    The bold is an extension function on SpannableStringBuilder. You can see the documentation here for a list of operations you can use.

    Another example:

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

    Where green is a resolved RGB color.

    It is even possible to nest spans so you end up with an embedded DSL:

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

    You will need the following in your app module level build.gradle for it to work:

    repositories {
        google()
    }
    
    dependencies {
        implementation "androidx.core:core-ktx:1.2.0"
    }
    
    0 讨论(0)
  • 2020-11-28 03:52

    The accepted answer is fine (and I upvoted it), but it fails to use the SpannableStringBuilder as the submitter requested. As I had a case where the Builder made the most sense, here is the code for that (with a bonus use of also changing the color of the text if that is helpful to others). Note that you could also provide the initial string to the SpannableStringBuilder constructor, but I set it here to use "append" to be clear that you can append a lot before your desired "bold" text and then just record the start as shown. I would suspect that this is also faster code than the accepted answer.

    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");
    
    0 讨论(0)
提交回复
热议问题