Android SpannableString establece el fondo detrás de una parte del texto

Me gustaría crear algo similar como se ve en esta imagen: enter image description here

Logré crear evertyhing con SpannableStringBuilder, excepto el rectángulo naranja redondeado. Puedo establecer el fondo de ese color con BackgroundColorSpan, pero no puedo encontrar la manera de redondearlo. ¿Alguna idea de cómo puedo lograr esto?

¡Gracias por adelantado!

EDITAR: estoy usando Xamarin.Android, pero aquí está mi código:

stringBuilder.SetSpan(new BackgroundColorSpan(Application.Context.Resources.GetColor(Resource.Color.orangeColor)), stringBuilder.Length() - length, stringBuilder.Length(), SpanTypes.ExclusiveExclusive); 

Si alguien tiene problemas con la muestra del código de Roosevelt (estoy seguro, tal vez porque es Xamarin.Android?), Aquí hay una traducción a una versión Java de Android más básica:

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

Y para su uso, el siguiente segmento de código se toma de una Actividad y básicamente pone un bonito fondo de esquina redondeada alrededor de cada cadena de tags, con un búfer espacial entre cada etiqueta. Tenga en cuenta que la línea comentada solo pone un color de fondo, que no produce un aspecto tan agradable …

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

Logré resolver mi problema, basado en la sugerencia de pskink. Aquí está mi clase:

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

Ejemplo de uso:

 var stringBuilder = new SpannableStringBuilder(); var stringToAppend = "hello world"; stringBuilder.Append(stringToAppend); stringBuilder.SetSpan(new RoundedBackgroundSpan(), stringBuilder.Length() - stringToAppend.Length, stringBuilder.Length(), SpanTypes.ExclusiveExclusive); 

solo una palabra: ReplacementSpan