简体   繁体   中英

Custom Drawable border overlaps with App Bar Layout Header

This is how my custom drawable looks by default.

在此处输入图片说明

But when scrolled, it overlaps with the AppBarLayout.

在此处输入图片说明

The code for the Drawable goes like this:

@Override
public void draw(@NonNull Canvas canvas) {

    // get drawable dimensions
    Rect bounds = getBounds();

    float width = bounds.right - bounds.left;
    float height = bounds.bottom - bounds.top;
    float w2 = width / 2;
    float h2 = height / 2;
    float radius = Math.min(w2, h2) - mStrokeWidth / 2;

    mPath.reset();
    mPath.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
    canvas.clipPath(mPath);

    // draw background gradient

    float barHeight = height / themeColors.length;
    mRectF.left = 0;
    mRectF.top = 0;
    mRectF.right = width;
    mRectF.bottom = height;
    for (int i = 0; i < themeColors.length; i++) {
        mPaint.setColor(themeColors[i]);

        canvas.drawRect(0, i * barHeight, width, (i + 1) * barHeight, mPaint);
    }

    mRectF.set(0, 0, width, height);
    canvas.clipRect(mRectF, Region.Op.REPLACE);

    if (mStrokeWidth != 0)
        canvas.drawCircle(width / 2, height / 2, width / 2 - mStrokeWidth / 2, mStrokePaint);

}

Support Library Version: 25.3.1, 26.1.0

What I've tried: - Different Region values for clipping path instead of REPLACE - Clipping path rectangle first and then clipping circle.

How do I fix this ?

I am posting my solution as answer.

The reason it was getting overlapped was because the canvas was getting clipped twice without saving it.

I removed this statement:

canvas.clipRect(mRectF, Region.Op.REPLACE);

and before clipping the canvas for the first time i saved its state using

canvas.save();
canvas.clipPath(mPath);

and then when i was drawing the stroke, i need the original canvas so i restored it

canvas.restore();
if (mStrokeWidth != 0)
    canvas.drawCircle(width / 2, height / 2, width / 2 - mStrokeWidth / 2, mStrokePaint);

This fixed the issue.

Final Drawable Code:

@Override
public void draw(@NonNull Canvas canvas) {

    // get drawable dimensions
    Rect bounds = getBounds();

    float width = bounds.right - bounds.left;
    float height = bounds.bottom - bounds.top;
    float w2 = width / 2;
    float h2 = height / 2;
    float radius = Math.min(w2, h2) - mStrokeWidth / 2;

    mPath.reset();
    mPath.addCircle(width / 2, height / 2, radius, Path.Direction.CW);
    canvas.save();
    canvas.clipPath(mPath);

    // draw background gradient

    float barHeight = height / themeColors.length;
    mRectF.left = 0;
    mRectF.top = 0;
    mRectF.right = width;
    mRectF.bottom = height;
    for (int i = 0; i < themeColors.length; i++) {
        mPaint.setColor(themeColors[i]);

        canvas.drawRect(0, i * barHeight, width, (i + 1) * barHeight, mPaint);
    }

    mRectF.set(0, 0, width, height);
    //canvas.clipRect(mRectF, Region.Op.REPLACE);
    canvas.restore();

    if (mStrokeWidth != 0)
        canvas.drawCircle(width / 2, height / 2, width / 2 - mStrokeWidth / 2, mStrokePaint);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM