由间隔

时间:2016-08-08 14:43:03

标签: android canvas bitmap porter-duff

拉我听到这个。我有一个背景位图,我想覆盖另一个具有透明剪切的位图。如果切口是基本形状,我没有问题,但是我需要将切口作为两个圆的交叉(一种叶子形状)。我尝试制作第三个位图以生成剪切模板,但我甚至无法获得剪裁的清晰表示,更不用说让它作为剪切模板工作了。

任何人都知道如何做这样的事情?这是我的(简化)尝试:

@Override
public void draw(Canvas canvas) {
    float w = canvas.getWidth();
    float h = canvas.getHeight();

    // just used to set some proportions
    float off = 300f;

    Paint paint = new Paint();

    // make a background bitmap with a yellow to green gradient
    Bitmap bitmapBkg = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888);
    Canvas canvasBkg = new Canvas(bitmapBkg);
    paint.reset();
    paint.setShader(new LinearGradient(0, h/2 - off, 0, h/2 + off, Color.YELLOW, Color.GREEN, Shader.TileMode.CLAMP));
    canvasBkg.drawRect(new RectF(0, 0, w, h), paint);

    // make an overlay bitmap with a red to magenta gradient which will have the cutouts
    Bitmap bitmapOver = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888);
    Canvas canvasOver = new Canvas(bitmapOver);
    paint.reset();
    paint.setShader(new LinearGradient(0, h/2 - off, 0, h/2 + off, Color.RED, Color.MAGENTA, Shader.TileMode.CLAMP));
    canvasOver.drawRect(new RectF(0, 0, w, h), paint);

    // make a bitmap of intersecting circles to be used as the cutout shape
    Bitmap bitmapCut = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888);
    Canvas canvasCut = new Canvas(bitmapCut);

    paint.reset();
    paint.setColor(Color.BLACK);
    //paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
    canvasCut.drawCircle(w / 2 - (off / 2 ), h / 2, off, paint);

    paint.reset();
    paint.setColor(Color.BLACK);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
    canvasCut.drawCircle(w / 2 + (off / 2), h / 2, off, paint);

    // apply cutout to overlay
    paint.reset();
    paint.setColor(Color.BLACK);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
    canvasOver.drawBitmap(bitmapCut, 0, 0, paint);

    // draw background and overlay onto main canvas
    paint.reset();
    paint.setColor(Color.BLACK);
    canvas.drawBitmap(bitmapBkg, 0, 0, paint);
    canvas.drawBitmap(bitmapOver, 0, 0, paint);
}

以下是我得到的图片:

enter image description here

我想要的是外部还有红洋红色;只有中间的眼形应该是黄绿色。

1 个答案:

答案 0 :(得分:0)

原来的诀窍是添加另一层。

    // make a secondary overlay that cuts out the whole circles
    Bitmap bitmapOver2 = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888);
    Canvas canvasOver2 = new Canvas(bitmapOver2);
    paint.reset();
    paint.setShader(new LinearGradient(0, h / 2 - off, 0, h / 2 + off, Color.RED, Color.MAGENTA, Shader.TileMode.CLAMP));
    canvasOver2.drawRect(new RectF(0, 0, w, h), paint);
    paint.reset();
    paint.setColor(Color.BLACK);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    canvasOver2.drawCircle(w / 2 - (off / 2), h / 2, off, paint);
    canvasOver2.drawCircle(w / 2 + (off / 2), h / 2, off, paint);

像这样应用:

    // draw background and overlay onto main canvas
    paint.reset();
    paint.setColor(Color.BLACK);
    canvas.drawBitmap(bitmapBkg, 0, 0, paint);
    canvas.drawBitmap(bitmapOver2, 0, 0, paint);
    canvas.drawBitmap(bitmapOver, 0, 0, paint);

基本上这是一个小技巧。它绘制了两次中间背景,一次是圆形切口,另一次是眼形切口。两者恰好合在一起,以达到理想的效果。

当然@Rotwang,你可能是对的。使用PatharcTo()将是一个更好的解决方案。我避免使用这种方法的唯一原因是b / c arcTo()是一个api 21+功能。到目前为止,我已经将api保持在17岁以上。但是,如果其他任何人想要提供一个arcTo()完整性的解决方案,那将很难比较。