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

AndroidSpannablestringSpannablestringbuilder

Android Problem Overview


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

So I want to know how I could use SpannableStringBuilder to do this?

I could use three TextEdit to accomplish this but I would like to use best solution.

Android Solutions


Solution 1 - Android

First Part Not Bold   BOLD  rest not bold

You can do this either as @Rajesh suggested or by this.

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

to show this in TextView

textview.setText(sb,  TextView.BufferType.SPANNABLE);

Solution 2 - Android

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

Solution 3 - Android

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

Solution 4 - Android

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

Solution 5 - Android

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

Solution 6 - Android

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.

Solution 7 - Android

We can also use SpannableStringBuilder with TextAppearanceSpan to accomplish that. Follow the below steps to implement like that.

  1. Create a style in styles.xml.

  1. Use the below code.
    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);
    

That's it. Hope it'll help someone.

Solution 8 - Android

So I know this has been solved, and even as requested with SpannableStringBuilder but in the event you wanted to build a string more dynamically I figured I would put this up.

// 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 is a ContentValues type that I constructed from the returned Cursor type of the SQL query. The only problem I had with this was at first it was only ColorSpaning the first segment. It seams that you need to declare a new ForegroundColorSpan every time you want to use one (or any other kind of span) in a loop.

Solution 9 - Android

you can bold and resize a part of your string in 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

Solution 10 - Android

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

Solution 11 - Android

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCode DroidView Question on Stackoverflow
Solution 1 - AndroidMohammed Azharuddin ShaikhView Answer on Stackoverflow
Solution 2 - AndroidJoshView Answer on Stackoverflow
Solution 3 - AndroidDavid RawsonView Answer on Stackoverflow
Solution 4 - AndroidGoberView Answer on Stackoverflow
Solution 5 - AndroidRajeshView Answer on Stackoverflow
Solution 6 - Androidlive-loveView Answer on Stackoverflow
Solution 7 - AndroidMahendran SakkaraiView Answer on Stackoverflow
Solution 8 - AndroidZeppieView Answer on Stackoverflow
Solution 9 - AndroidReza ZavarehView Answer on Stackoverflow
Solution 10 - AndroidqtyqView Answer on Stackoverflow
Solution 11 - AndroidKennyAliView Answer on Stackoverflow