Adding a padding/margin to a Spannable

Henrique picture Henrique · Nov 29, 2014 · Viewed 12.4k times · Source

I'm using BackgroundColorSpan to customize parts of a TextView. Here's the code I have:

String s = "9.5 Excellent!";
s.setSpan(new BackgroundColorSpan(darkBlue, 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(new BackgroundColorSpan(darkBlue, 3, 14, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

Which gives me the following result:

Have

And this is what I'm trying to achieve:

Want

As you can see, I'm trying to add a padding to the "9.5" as well as the "excellent!" Strings, but I've been unable to find a solution so far.

Is there a way to add this padding/margin to these Spannables?

Answer

Andrea Motto picture Andrea Motto · Mar 13, 2015

You can use ReplacementSpan. In your Activity:

TextView tagsTextView = (TextView) mView.findViewById(R.id.tagsTextView);
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();

SpannableString tag1 = new SpannableString("9.5");
stringBuilder.append(tag1);
stringBuilder.setSpan(new TagSpan(getResources().getColor(R.color.blue), getResources().getColor(R.color.white)), stringBuilder.length() - tag1.length(), stringBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

SpannableString tag2 = new SpannableString("excellent!");
stringBuilder.append(tag2);
stringBuilder.setSpan(new TagSpan(getResources().getColor(R.color.blueLight), getResources().getColor(R.color.blue)), stringBuilder.length() - tag2.length(), stringBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tagsTextView.setText(stringBuilder, TextView.BufferType.SPANNABLE);

TagSpan.java

public class TagSpan extends ReplacementSpan {
    private static final float PADDING = 50.0f;
    private RectF mRect;
    private int mBackgroundColor;
    private int mForegroundColor;

    public TagSpan(int backgroundColor, int foregroundColor) {
        this.mRect = new RectF();
        this.mBackgroundColor = backgroundColor;
        this.mForegroundColor = foregroundColor;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        // Background
        mRect.set(x, top, x + paint.measureText(text, start, end) + PADDING, bottom);
        paint.setColor(mBackgroundColor);
        canvas.drawRect(mRect, paint);

        // Text
        paint.setColor(mForegroundColor);
        int xPos = Math.round(x + (PADDING / 2));
        int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)) ;
        canvas.drawText(text, start, end, xPos, yPos, paint);
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
        return Math.round(paint.measureText(text, start, end) + PADDING);
    }
}