Android:在 canvas 中绘制背景图片

Android: painting over background picture in canvas

我尝试隐藏图片并在用户触摸屏幕时以交互方式显示图片的各个部分。我尝试了很多方法,比如让背景视图与我将使透明的视图重叠,但不知何故有效。最终的解决方案应该是单个自定义视图,这将给我更多的绘画灵活性。

Activity:

hiddenPicture.setBackgroundResource(R.drawable.picture);

查看:

init()
    eraserPaint = new Paint();
    eraserPaint.setColor(Color.TRANSPARENT);
    // eraserPaint.setAlpha(0);
    eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    veilPaint = new Paint();
    veilPaint.setColor(Color.GRAY);

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawRect(0, 0, w, h, veilPaint);
    canvas.drawOval(new RectF(20, 20, 220, 220), eraserPaint);
}

问题是椭圆是黑色的。我发现了很多类似的问题,但我 Android 太初级了,无法将它们应用到我的案例中。我该怎么做才能消除灰色面纱中的椭圆形并显示背景图片?谢谢。

更新:

我找到了不错的博客:http://www.41post.com/4794/programming/android-rendering-a-path-with-a-bitmap-fill

我将它回收到我的代码中:

    fillBMP = BitmapFactory.decodeResource(context.getResources(), R.drawable.picture);
    fillBmpShader = new BitmapShader(fillBMP, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    eraserPaint.setColor(0xFFFFFFFF);
    eraserPaint.setStyle(Paint.Style.FILL);
    eraserPaint.setShader(fillBmpShader);

它似乎可以工作,但问题是它不能缩放用作画笔的图像。确实是唯一以这种方式实施 onDraw() 的解决方案:

  1. 画图
  2. 除了未覆盖的部分外,涂上面纱

我担心性能。我不想在每次用户交互后绘制完整的屏幕。我宁愿只重绘相关部分。这甚至可能还是我已经过度优化了?

我必须维护和绘制两个位图 - 一个用于背景,第二个用于带有透明空心的面纱:

private void setupDrawing() {
    eraserPaint = new Paint();
    eraserPaint.setColor(Color.TRANSPARENT);
    eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    veilPaint = new Paint();
    veilPaint.setColor(Color.GREEN);
    canvasPaint = new Paint(Paint.DITHER_FLAG);
}

// http://developer.android.com/training/custom-views/custom-drawing.html
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    drawCanvas = new Canvas(canvasBitmap);
    drawCanvas.drawRect(0, 0, w, h, veilPaint);
}

protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(fillBitmap, 0, 0, canvasPaint);
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
}

public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_MOVE) {
        drawCanvas.drawCircle(event.getX(), event.getY(), 150, eraserPaint);
        invalidate();
    }
    return true;
}