如何在Android中将圆形路径裁剪为矩形内部?

13
我已经阅读了20多个问题/答案,但仍然无法得到我想要的。 我想在矩形内切一个圆,如下所示:

这是我的代码:

@Override
protected void onDraw(Canvas canvas) {
    Paint paint = new Paint();
    paint.setStyle(Paint.Style.FILL);
    paint.setARGB(180, 0, 0, 0);
    canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
    Path circularPath = new Path();
    circularPath.addCircle(getWidth() / 2, getHeight() / 2, radius, Path.Direction.CCW);
    canvas.clipPath(circularPath, Region.Op.REPLACE);
    canvas.drawColor(0x00000000);


}

我的背景(setARGB)显示正确,但没有被裁剪。我尝试了不同的Op值,而不是REPLACE,强制软件光栅化(因为我已经在某些Android版本上阅读到clipPath不支持一些Op)通过在构造函数中调用setLayerType(LAYER_TYPE_SOFTWARE, null); ,但没有效果。我该如何实现所需的效果?

注意:我的最小SDK版本是15,因此我不需要支持低于4.0的任何内容。


你尝试过使用 Region.Op.DIFFERENCE 吗? - pskink
1
@pskink 是的,我刚刚再次尝试了一下以确保。不幸的是,什么也没有发生。 - Can Poyrazoğlu
DIFFERENCE 对我来说很好用,尝试使用 Color.RED 进行 canvas.drawColor,然后进行 clipPath,最后再 drawColor 0x88000000。 - pskink
@pskink,您能否在回答中发布一个SSCCE? - Can Poyrazoğlu
2
canvas.drawColor(Color.RED); Path circularPath = new Path(); circularPath.addCircle(getWidth() / 2, getHeight() / 2, 300, Path.Direction.CCW); canvas.clipPath(circularPath, Region.Op.DIFFERENCE); canvas.drawColor(0x66000000); - pskink
@pskink,它有效。请将此评论发布为答案,以便我可以接受它。 - Can Poyrazoğlu
2个回答

5

在使用drawRect之前,请使用clipPath

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    int width = this.getWidth();
    int height = this.getHeight();

    mPaint.setAntiAlias(true);
    mPaint.setColor(Color.WHITE);
    mPaint.setStyle(Paint.Style.FILL);
    canvas.drawPaint(mPaint);

    float rectWidth = Utils.dpToPx(100.0f);

    Path circularPath = new Path();
    circularPath.addCircle(width / 2.0f, rectWidth / 2.0f, rectWidth / 3.0f, Path.Direction.CCW);
    canvas.clipPath(circularPath, Region.Op.DIFFERENCE);

    mPaint.setColor(Color.BLUE);
    canvas.drawRect((width - rectWidth) / 2.0f, 0.0f, ((width - rectWidth) / 2.0f) + rectWidth, rectWidth, mPaint);
}

Result


4

尝试在dispatchDraw()中剪裁您的路径:

@Override
protected void dispatchDraw(Canvas canvas)
{
    canvas.clipPath(mClipPath, mRegion); // previously created path & region

    super.dispatchDraw(canvas);
}

将路径剪辑代码从onDraw方法中删除,这样应该就可以了。

编辑:

创建路径时,请确保在测量发生后才进行此操作,例如:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    mClipPath.reset();
    float radius = Math.min((float)getMeasuredWidth() / 2f, (float)getMeasuredHeight() / 2f) + 5;
    mClipPath.addCircle((float)getMeasuredWidth() / 2f, (float)getMeasuredHeight() / 2f, radius, Path.Direction.CCW);
}

尝试过了,没有任何改变。 - Can Poyrazoğlu
我已经编辑了我的答案,包括可能导致它对你不起作用的原因。 - Gil Moshayof
2
复制/粘贴它。仍然没有更改。我严重怀疑除了onDraw方法之外还应该有覆盖的方法,因为我看到的所有示例都只涉及该方法。 - Can Poyrazoğlu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接