Android spannable string with line spacing
Asked Answered
R

1

10

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?

Rusticate answered 27/7, 2014 at 22:50 Comment(4)
Please can you be more specific about how you solved the problem. More code or something. It would be very useful to me.Omasum
The actual code for the solution is published above.Rusticate
@Rusticate can you please post the measureText() methodDegrading
private float measureText(Paint paint, CharSequence text, int start, int end) { return paint.measureText(text, start, end); }Rusticate
P
1

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);
    }
}
Prochoras answered 4/12, 2015 at 15:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.