Draw method for Spannable String is not called on Marshmallow

I have a calendar inside my application. The Calendar is a GridView with buttons for each date. I tried to paint them with the following class

public class CircleSpan extends ReplacementSpan {

private final float mPadding;
private final int mCircleColor;
private final int mTextColor;

public CircleSpan(Context context) {
    super();
    TypedArray ta = context.getTheme().obtainStyledAttributes(new int[]{
            R.color.current_day,
            android.R.attr.textColorPrimaryInverse
    });
    mCircleColor = ta.getColor(0, ContextCompat.getColor(context, R.color.current_day));
    //noinspection ResourceType
    mTextColor = ta.getColor(1, 0);
    ta.recycle();
    mPadding = context.getResources().getDimension(R.dimen.padding_circle);
}

@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
    Log.d("CircleSpan", "getSize");
    return Math.round(paint.measureText(text, start, end) + mPadding * 2); // left + right
}

@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
    if (TextUtils.isEmpty(text)) {
        Log.d("CircleSpan", "empty draw");
        return;
    }
    float textSize = paint.measureText(text, start, end);
    paint.setColor(mCircleColor);
    canvas.drawCircle(x + textSize / 2 + mPadding,
            (top + bottom) / 2, // center Y
            (text.length() == 1 ? textSize : textSize / 2) + mPadding,
            paint);
    paint.setColor(mTextColor);
    canvas.drawText(text, start, end, mPadding + x, y, paint);
    Log.d("CircleSpan", "draw");
}

      

}

I created a class and tested it with a Lollipop test device and everything worked fine. After that, I hosted the app on my Marshmallow device. The entries inside the calendar, which should be colored, are no longer visible. I found out that the draw method inside my CircleSpan class didn't even get a call.

With a little hack, I was able to get it to work, but I'm really not satisfied with the solution. It consists of a TextView that is not visible at the end of the screen, which is also colored with CircleSpan. The difference is expanding the text and just coloring everything except the expansion:

                // Absolutly hacked
        SpannableString spannable1 = new SpannableString(theday + " ");
        spannable1.setSpan(new CircleSpan(gridcell.getContext(), ColorType.NONE),
                0, theday.length() - 1,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        mHack.setText(spannable1, TextView.BufferType.SPANNABLE);

      

As long as the "hack" is inside the application, everything else is colored as I coded it. But I really don't know why. I read about ReplacementSpan in Android documentation: ReplacementSpan getSize

But the hint

Returns the width of the range. Extending classes can set the height of the range by updating the Paint.FontMetricsInt attributes. If span spans all text and no height is set, draw (Canvas, CharSequence, int, int, float, int, int, int, Paint) will not be called for the range.

doesn't help me. Does anyone have any idea how I can color my calendar entries with my class and without hacking? And why is the problem only on Marshmallow devices? I'm not sure about Nougat and what happens on devices below Lollipop.

I hope everyone can understand my bad English. Thanks in advance!

+3


source to share





All Articles