Canvas.clipPath(Path)不能按预期进行剪切

21

我正在尝试把画布绘制操作裁剪成弧形楔形。但是,设置画布的裁剪路径后,我没有得到预期的结果。

为了说明,这是我的操作:

enter image description here

path.reset();

//Move to point #1
path.moveTo(rect.centerX(), rect.centerY());

//Per the documentation, this will draw a connecting line from the current
//position to the starting position of the arc (at 0 degrees), add the arc
//and my current position now lies at #2.
path.arcTo(rect, 0, -30);

//This should then close the path, finishing back at the center point (#3)
path.close();

这个方法是有效的,在调用(canvas.drawPath(path, paint))后,扇形就会像上面展示的那样被绘制出来。然而,当我将这个路径设置为画布的剪切路径并在其内绘制时:

//I've tried it with and without the Region.Op parameter
canvas.clipPath(path, Region.Op.REPLACE);
canvas.drawColor(Color.BLUE);

我得到了以下结果(为了方便参考,楔形仍然存在):

enter image description here

所以它似乎只裁剪Path的边界矩形,而不是Path本身。有什么想法吗?

编辑 作为更新,我找到了一种更有效的方法来实现这个目的,它可以进行硬件加速。首先,将整个图像(您要剪裁的图像)绘制到离屏位图中。使用此Bitmap创建一个BitmapShader,将该着色器设置为Paint,然后使用该Paint对象绘制楔形路径:

drawMyBitmap(bitmap);
Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setShader(shader);

@Override
public void onDraw(Canvas canvas) {
    canvas.drawArc(rect,         //The rectangle bounding the circle
                   startAngle,   //The angle (CW from 3 o'clock) to start
                   sweepAngle,   //The angle (CW from 3 o'clock) of the arc
                   true,         //Boolean of whether to draw a filled arc (wedge)
                   paint         //The paint with the shader attached
    );
}

1
你是否正在使用HC或以上版本,或者正在使用硬件加速?如果是的话,clipPath不受支持且存在问题。http://developer.android.com/guide/topics/graphics/hardware-accel.html。 - Simon
1
@Simon:天啊。哈哈。不幸的是,这个星期我一直在参考那个文档,但是我完全忽略了那个。禁用硬件加速完美地解决了问题!如果你能把这个作为答案发表,我会接受它。你是我的救命恩人! - Kevin Coppock
很高兴能够帮助。祝你好运。 - Simon
美妙的问题! - swooby
你如何实现这个功能呢?首先,将整个图像(需要剪切的部分)绘制到一个离屏位图中。 - Interkot
2个回答

13

1
那就是问题所在。 :) 将绘图操作的剪切部分移动到离屏位图中,然后将其绘制回硬件加速画布上,它就像魔法一样运作了!再次感谢! - Kevin Coppock
1
@kcoppock 听起来有点反过来了。为什么不将视图的层类型转换为软件,然后在 onDraw() 中进行绘制呢? - Richard J. Ross III
@RichardJ.RossIII 那样做更有意义。 :) 当时我有点不熟悉。现在我已经编辑了新的处理方法,感谢您的建议! - Kevin Coppock

3

OP的问题特别涉及使用剪切区域,并已由@Simon回答。但请记住,有一种更简单的方法来绘制填充弧线:

创建一个Paint

mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Style.FILL);
mPaint.setAntiAlias(true);

绘制时,只需绘制路径:

canvas.drawPath(path, mPaint);

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