Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android spannable string with line spacing

I have a tag cloud in which the tags have a background color. Unfortunately I am not able to get a line spacing in place.

Let's assume this is the text cloud:

tag1  tag2  tag3
tagtext4 tagtext5

This is the style for the text view:

<style name="DataEntryValue" parent="@android:style/TextAppearance.Medium">
    <item name="android:textColor">@color/gray_value</item>
    <item name="android:fontFamily">sans-serif-condensed</item>
</style>

BackgroundColorSpan is used to set a blue background color for the tags. However there is no space between the lines i.e. the background color of the two lines are not separated.

When I set the line spacing for the text view e.g. to 12sp, it adds line spacing but uses the background color for the tag instead of a the textview background color to establish the line spacing.

Any idea how I can get the line spacing using the text view background color?

Update

Using this solution as a guidance I came up with this approach: draw the background for the text, draw the background for the text with padding at top and bottom, draw the text. As I have not used canvas before, there might be a better approach. Anyway - here is the code.

    public void draw(Canvas canvas, CharSequence text, int start, int end, float x,
            int top, int y, int bottom, Paint paint)
    {

        float padding;
        float right
        RectF rect;

        right =  x + measureText(paint, text, start, end);

        padding = 4f;

        rect = new RectF( x, top, right, bottom );  

        paint.setColor( mContext.getResources().getColor(R.color.color1) );         

        rect = new RectF( x, top + padding, right, bottom - padding);   

        paint.setColor( mContext.getResources().getColor(R.color.bg_color_tag_item) );          
        canvas.drawRect(rect, paint);

        paint.setColor( mContext.getResources().getColor(R.color.data_entry_value) );

        canvas.drawText(text, start, end, x, y, paint);
    }

And it looks like this now:

enter image description here

Nice to know: is there better solution?

like image 774
user3460486 Avatar asked Jul 27 '14 22:07

user3460486


1 Answers

I found a better solution that uses a ReplacementSpan : we can override the function draw and draw a rectangle behind our text. It's more flexible. You just have to give it the text height.

/**
 * It's like a {@link android.text.style.BackgroundColorSpan} but we don't paint the extra line height.
 * <p/>
 */
public class BackgroundColorWithoutLineHeightSpan extends ReplacementSpan
{
    private final int mColor;
    private final int mTextHeight;

    public BackgroundColorWithoutLineHeightSpan(int color, int textHeight)
    {
        mColor = color;
        mTextHeight = textHeight;
    }

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

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)
    {
        int paintColor = paint.getColor();
        RectF rect = new RectF(x, top, x + measureText(paint, text, start, end), top + mTextHeight);
        paint.setColor(mColor);
        canvas.drawRect(rect, paint);
        paint.setColor(paintColor);
        canvas.drawText(text, start, end, x, y, paint);
    }

    private float measureText(Paint paint, CharSequence text, int start, int end)
    {
        return paint.measureText(text, start, end);
    }
}
like image 137
Sylphe Avatar answered Sep 21 '22 07:09

Sylphe