我想画一条类似于图像的路径。它有两个黑色边框,里面是白色而不是透明。怎么实现呢?尤其是关节位置。
答案 0 :(得分:19)
要获得所需的结果,您必须绘制部分路径。
您将使用两个不同的Paint
对象绘制两次零件,仅在笔划宽度和颜色方面有所不同。绘制每个零件后,将重置路径。代码注释应解释其余部分:
public class SView extends View {
Path path;
Paint paint, paintWhite;
RectF rf, rf2, rf3;
public SView(Context context) {
super(context);
path = new Path();
// 'paint' has a wider stroke-width
// compared to 'paintWhite' and
// thus becomes the border paint
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setStrokeWidth(15);
paint.setStyle(Style.STROKE);
// 'paintWhite' colors the inner path
paintWhite = new Paint();
paintWhite.setColor(Color.WHITE);
paintWhite.setAntiAlias(true);
paintWhite.setStrokeWidth(12);
paintWhite.setStyle(Style.STROKE);
// For this example, we'll draw three
// arcs bound by the following RectF
// objects
rf = new RectF(200, 200, 500, 500);
rf2 = new RectF(200, 200, 400, 500);
rf3 = new RectF(100, 200, 400, 500);
}
@Override
protected void onDraw(Canvas canvas) {
// First arc bound by 'rf'
path.arcTo(rf, 0, 180);
// Draw 'path' using 'paint'
// and then, again using 'paintWhite'
canvas.drawPath(path, paint);
canvas.drawPath(path, paintWhite);
// Reset 'path' so as to clear
// history
path.reset();
// Repeat with the rest of arcs
path.arcTo(rf2, 180, 180);
canvas.drawPath(path, paint);
canvas.drawPath(path, paintWhite);
path.reset();
path.arcTo(rf3, 0, 180);
canvas.drawPath(path, paint);
canvas.drawPath(path, paintWhite);
}
}
输出:
注意:重叠的弧由RectF rf3
绑定,最后绘制。
由于我们正在绘制white
部分以及borders
,因此您不会以四路交叉结束。这些部分将以flyover
种方式重叠:按绘制顺序重叠。
为了提高性能(我想),您可以在重置路径之前检查路径的下一部分是否与之前的路径相交。如果下一个零件相交,则使用两个Paint对象重置并绘制零件。如果没有,只需将零件附加到路径并等到下一个交叉点绘制它。您当然需要保留绘制零件的历史记录(在上面的示例中,历史记录将包含边界:'RectF'对象)。但是,我不是100%确定这是否比重复重置路径然后绘制零件更好。
答案 1 :(得分:1)
您可以尝试使用两个不同的Paint对象来绘制相同的路径。第一个Paint对象将具有边框所需的颜色和较大的笔触宽度。第二个Paint的笔画宽度较小,其上设置了PorterDuff.Mode.CLEAR
。
linePaint = new Paint();
linePaint.setAntiAlias(true);
linePaint.setColor(Color.YELLOW);
linePaint.setStrokeWidth(6);
linePaint.setStyle(Paint.Style.STROKE);
clearPaint = new Paint();
clearPaint.setAntiAlias(true);
clearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
clearPaint.setStyle(Paint.Style.STROKE);
clearPaint.setStrokeWidth(3);
然后在你的onDraw()方法中,使用上面两种颜色绘制相同的路径两次。
canvas.drawPath(path, linePaint);
canvas.drawPath(path, clearPaint);
这在性能方面可能效率不高,但这是我能想到的最简单的方法。
编辑:我自己没有彻底测试过,所以如果有任何问题请告诉我。更新:经过测试,我发现PorterDuff.Mode.CLEAR将清除画布的后备位图中存在的整个像素信息。所以人们通常会得到这样的结论:
解决此问题的方法是创建一个离屏画布来绘制路径。
Canvas canvas2 = new Canvas();
Bitmap backingBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
canvas2.setBitmap(backingBitmap);
canvas2.drawPaint(clearPaint);
canvas2.drawPath(path, linePaint);
canvas2.drawPath(path, clearPaint);
canvas.drawBitmap(backingBitmap, 0, 0, null);
使用上述方法,您将获得以下结果:
缺点是,如果你每帧都这样做,创建位图可能会影响性能。位图的大小也会对性能产生负面影响。因此,您只需要在必要时创建离屏画布,只要您不需要重置路径信息,就可以继续绘制到之前创建的backingBitmap。