Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android SpannableString set background behind part of text

I would like to create something similar as seen on this image: enter image description here

I managed to create evertyhing with SpannableStringBuilder, except the orange rounded rectangle. I can set the background to that color with BackgroundColorSpan, but I can't find a way to make it rounded. Any ideas how can I achieve this?

Thanks in advance!

EDIT: I'm using Xamarin.Android, but here is my code:

stringBuilder.SetSpan(new BackgroundColorSpan(Application.Context.Resources.GetColor(Resource.Color.orangeColor)), stringBuilder.Length() - length, stringBuilder.Length(), SpanTypes.ExclusiveExclusive); 
like image 722
Roosevelt Avatar asked Oct 10 '13 10:10

Roosevelt


People also ask

How to change the text color of a substring in Android?

How to change the Text Color of a Substring in android using SpannableString class? 1 Add the following code in activity_main.xml file. This will add two textviews in the activity_main layout. 2 Now add the following code in the MainActivity.java file. In this code we will change the color of substrings of first textview with SpannableString ...

What is the use of spannablestringbuilder in Android?

SpannableString: This is used when there is no need to modify the text but you need to modify the markup i.e. you need to add some spans to your text. SpannableStringBuilder: This is used when you need to modify the text as well as the markup. This is a quick intro about the Spans in Android. Now, let's see some of the use-cases of it.

How to spannable text from a textview?

We pass in the start and end index together with the appropriate flag, and we set the text in the TextView to the created spannable. We then come up with this! We follow the same approach as before in getting a reference to the TextView and creating a method to setup the foreground span effect.

How to change the background color of a string in Java?

It is easy to change the color of the whole string but to change the color of a substring we have to use a special class SpannableString. But SpannableString class is not really helpful when it comes to change the background color of the text. So for that, we have to use SpannableStringBuilder class.


2 Answers

If anyone's having difficulty with Roosevelt's code sample (I sure was, maybe because it's Xamarin.Android?), here's a translation into a more basic Android java version:

     public class RoundedBackgroundSpan extends ReplacementSpan {          private static int CORNER_RADIUS = 8;         private int backgroundColor = 0;         private int textColor = 0;          public RoundedBackgroundSpan(Context context) {             super();             backgroundColor = context.getResources().getColor(R.color.gray);             textColor = context.getResources().getColor(R.color.white);         }          @Override         public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {             RectF rect = new RectF(x, top, x + measureText(paint, text, start, end), bottom);             paint.setColor(backgroundColor);             canvas.drawRoundRect(rect, CORNER_RADIUS, CORNER_RADIUS, paint);             paint.setColor(textColor);             canvas.drawText(text, start, end, x, y, paint);         }          @Override         public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {             return Math.round(paint.measureText(text, start, end));         }          private float measureText(Paint paint, CharSequence text, int start, int end) {             return paint.measureText(text, start, end);         }     } 

And for usage, the following code segment is taken from an Activity and basically puts a nice rounded-corner background around each tag string, with a spacial buffer in between each tag. Note that the commented out line just puts in a background color, which doesn't produce as nice a look...

     SpannableStringBuilder stringBuilder = new SpannableStringBuilder();      String between = "";     for (String tag : eventListing.getTags()) {        stringBuilder.append(between);        if (between.length() == 0) between = "  ";        String thisTag = "  "+tag+"  ";        stringBuilder.append(thisTag);        stringBuilder.setSpan(new RoundedBackgroundSpan(this), stringBuilder.length() - thisTag.length(), stringBuilder.length() - thisTag.length() + thisTag.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);        //stringBuilder.setSpan(new BackgroundColorSpan(getResources().getColor(R.color.gray)), stringBuilder.length() - thisTag.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     }      TextView tv = new TextView(this);     tv.setText(stringBuilder); 
like image 126
jkincali Avatar answered Sep 19 '22 11:09

jkincali


I managed to solve my problem, based on pskink's suggestion. Here is my class:

public class RoundedBackgroundSpan : ReplacementSpan {     public override void Draw(Canvas canvas, ICharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)     {         var rect = new RectF(x, top, x + MeasureText(paint, text, start, end), bottom);         paint.Color = Application.Context.Resources.GetColor(Resource.Color.nextTimeBackgroundColor);         canvas.DrawRoundRect(rect, Application.Context.Resources.GetDimensionPixelSize(Resource.Dimension.localRouteDetailsRoundRectValue), Application.Context.Resources.GetDimensionPixelSize(Resource.Dimension.localRouteDetailsRoundRectValue), paint);         paint.Color = Application.Context.Resources.GetColor(Resource.Color.nextTimeTextColor);         canvas.DrawText(text, start, end, x, y, paint);     }      public override int GetSize(Paint paint, ICharSequence text, int start, int end, Paint.FontMetricsInt fm)     {         return Math.Round(MeasureText(paint, text, start, end));     }      private float MeasureText(Paint paint, ICharSequence text, int start, int end)     {         return paint.MeasureText(text, start, end);     } } 

Example usage:

var stringBuilder = new SpannableStringBuilder(); var stringToAppend = "hello world"; stringBuilder.Append(stringToAppend); stringBuilder.SetSpan(new RoundedBackgroundSpan(), stringBuilder.Length() - stringToAppend.Length, stringBuilder.Length(), SpanTypes.ExclusiveExclusive); 
like image 25
Roosevelt Avatar answered Sep 22 '22 11:09

Roosevelt