I have an app where I am displaying multiple lines, and multiple paragraphs, of formatted text in a TextView
. I am using SpannableStringBuilder
for this purpose.
One of the things I want to do here is to be able to highlight the text. Now I have tried using BackgroundColorSpan
, but in this case, the background on the text covers the complete line-height. I want it to cover only the text instead. There seems to be no apparent way to set a vertical padding or height on this span. Just the colour.
Secondly, I also tried subclassing ReplacementSpan
and implementing a backgroundSpan
of my own by drawing in the draw method of this class. But this doesn't seem to support multiline highlighting.
Can anyone tell me how I can go about achieving this highlighting functionality? Basically, I want it to work like an ebook reader, preferably the Kindle
or the default Book reader on Android
.
I tried the solution of koopuluri, but the LineBackgroundSpan is for an entire paragraph when just I wanted to highlight some words. So I found the ReplacementSpan, where we can override the function draw
and draw a rectangle behind our text. You 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);
}
}
You can implement LineBackgroundSpan and override:
drawBackground (Canvas c, Paint p, int left, int right, int top, int baseline, int bottom, CharSequence text, int start, int end, int lnum)
You can modify the "top" and "bottom" arguments to specify the height of the background you are drawing for a given line. The "baseline" argument is the the y-coordinate of the line that all the characters sit on (notice that the letters g, p, j etc. have some parts that fall below the baseline).
This method is applied for every line on the display for a given text. For example if the text
"this is an example , blah, blah .."
spans 3 lines on your display, then drawBackground(...) is applied thrice, and you can use the "lnum" argument to change the behavior for certain lines if you are looking to only change the height of certain lines in the span.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With