使用Canvas.drawColor()清除画布

13
我试图更改自定义视图的背景图像,有些成功。图片会改变,但问题是我仍然看到旧图片的痕迹。当我尝试在绘制新图片之前清除画布时,它似乎不起作用。我创建一个位图来存储图片。在更改图片时,我在绘制新图片之前调用Canvas.drawColor(),但旧图片仍然存在。我尝试了drawColor(0),drawColor(Color.BLACK),c.drawColor(0, PorterDuff.Mode.CLEAR)等方法,但以上都不起作用。因此,我不得不向比我更有经验的人请教。实际代码如下:
private int bgnd;
private boolean switching;

public void setBgnd(int incoming){
    switching = true;
    switch (incoming){

    case R.drawable.image1:
        bgnd = incoming;
        this.invalidate();
        break;

    case R.drawable.image2:
        bgnd = incoming;
        this.invalidate();
        break;

    }
}



protected void onDraw(Canvas c){
    if(switching == true){
        Bitmap b = BitmapFactory.decodeResource(getResources(), bgnd);
        c.drawColor(0, PorterDuff.Mode.CLEAR);
        c.drawBitmap(b, 0, 0, null);
        switching = false;

    }else{
        Bitmap b = BitmapFactory.decodeResource(getResources(), bgnd);
        c.drawBitmap(b, 0, 0, null);
    }
}
4个回答

31

就像你一样,我曾经苦恼于如何在多层/表面视图应用程序中清除顶部层/表面视图。经过两天的搜索和编写代码,我找到了自己的方法,以下是我在绘制前清除画布的方法,在具有多个层/表面视图时可以使用。背景层不会被覆盖为黑色,这就是诀窍。

Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
canvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC));
// start your own drawing

1
我认为如果没有strangeInAStrangerLand和longdooooo的帮助,我可能需要超过2天的时间才能解决这个问题,但现在只用了2分钟就搞定了。非常感谢他们! - Mark Lapasa

3
您可以使用Canvas的方法drawRGB

drawRGB()不清除alpha通道,位图将变得不透明,因此它只能在位图是唯一图层或背景图层时使用。还有一个方法drawARGB(),它允许处理alpha通道。虽然我还没有尝试过它是否有效。 - Oliver Hausler
1
请注意,drawRGB 只是使用 drawColor(Color.rgb(r, g, b)) - TameHog

2

你不需要在onDraw方法中调用invalidate()吗?这样可以使得在onDraw中做出的改变在屏幕上更新。

在switch语句中调用invalidate()会在你调用setBgnd之后触发onDraw,但是没有任何指示在对Canvas进行更改后重新绘制。


1
我印象中调用invalidate()会告诉一个视图调用onDraw()并绘制自己。既然如此,在该方法中放置该调用将导致它无限循环,就像在以下示例中所看到的: http://www.anddev.org/basic_and_simple_2d_drawing_-_animation-t3085.html - Prmths
啊,你说得对,我去查了一下,http://developer.android.com/guide/topics/graphics/index.html。抱歉我的理解不正确。 - C0deAttack
我一开始也是这么想的。对我来说问题是,如果invalidate()命令视图重新绘制自己,为什么在动画后期之前它不会完全重绘自己?对象的下半部分看起来正确,但另一半仍然是旧表面。 - Prmths
我也尝试使用8位图像,因为我读到Android在处理32位图像时可能会出现问题。但我并不认为这是问题的原因,而且我发现这并没有帮助。我还尝试了setBackgroundResource()(实际上是我先尝试的,甚至在使用画布之前),但它也不起作用,即使在onDraw()内部调用也是如此。 - Prmths

0

我刚遇到了这个问题。

我通过至少重复“..Drawxxx();Post();” 3次来解决它,它很好地工作了。

我猜测,“双缓冲”是原因,有时候是“三倍缓冲”。我们需要重复绘制以确保每个“缓冲区”都得到更新。


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