web-dev-qa-db-fra.com

Android SpannableString définit l'arrière-plan derrière une partie du texte

Je voudrais créer quelque chose de similaire comme on le voit sur cette image: enter image description here

J'ai réussi à créer tout avec SpannableStringBuilder, sauf le rectangle arrondi orange. Je peux définir l'arrière-plan sur cette couleur avec BackgroundColorSpan, mais je ne trouve pas de moyen de le rendre arrondi. Des idées comment puis-je y parvenir?

Merci d'avance!

EDIT: J'utilise Xamarin.Android, mais voici mon code:

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

J'ai réussi à résoudre mon problème, sur la base de la suggestion de pskink. Voici ma classe:

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

Exemple d'utilisation:

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

Si quelqu'un a des problèmes avec l'exemple de code de Roosevelt (j'en étais sûr, peut-être parce que c'est Xamarin.Android?), Voici une traduction en une version plus basique 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);
        }
    }

Et pour l'utilisation, le segment de code suivant est tiré d'une activité et met essentiellement un joli fond aux coins arrondis autour de chaque chaîne de balise, avec un tampon spatial entre chaque balise. Notez que la ligne commentée met simplement une couleur d'arrière-plan, ce qui ne produit pas un look aussi agréable ...


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

un seul mot: ReplacementSpan

4
pskink