I would like to create something similar as seen on this image:
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);
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 ...
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.
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.
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.
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);
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With