Android SurfaceView不保留以前绘制的对象

时间:2014-05-13 03:05:04

标签: android android-canvas surfaceview surfaceholder

我正在尝试使用SurfaceView。我的要求是首先简单地渲染一个节点(简单的drawable)。然后,在稍后的时间点渲染更多节点

我线程的运行方法和片段的片段我的doDraw方法如下。我只想在后续传球中渲染2个不同的抽签,同时保留两者。问题是它消除了第一遍中写入的内容(请参阅代码中的注释)。 如何保留以前绘制的对象?

    public void run() {
        Canvas canvas;
        while (_running) {
            canvas = null;
            try {
                canvas = _surfaceHolder.lockCanvas(null);
                synchronized (_surfaceHolder) {
                    doDraw(canvas, isUpdate);
                }
            } finally {
                if (canvas != null) {
                    _surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }


    public void doDraw(Canvas canvas, boolean update){
        if(update){
            //goes here 2nd pass & wipes away things done in 1st pass
            //I want to retain whatever was drawn in 1st pass
            Bitmap thumb = BitmapFactory.decodeResource(getResources(),R.drawable.icon);
            //canvas.drawColor(Color.RED);
            canvas.drawBitmap(thumb, 0, 0, null);
        } else{
            //goes here 1st pass
            Bitmap thumb = BitmapFactory.decodeResource(getResources(), R.drawable.thumb);
            //canvas.drawColor(Color.BLACK);
            canvas.drawBitmap(thumb, 300, 300, null);
            this.isUpdate = true;
        }
    }

更新1: 似乎仍然没有奏效。我将运行代码更改为通过非:

     public void run() {
        Canvas canvas;
        while (_running) {
            canvas = null;
            try {
                Rect dty = null;
                if(isUpdate == true){
//--> In 2nd pass, I was hoping that only these co-ordinates will be updated
                    dty = new Rect(0,0,100,100);  
                    canvas = _surfaceHolder.lockCanvas(dty);
                }else{
                    canvas = _surfaceHolder.lockCanvas(null);
                }
                synchronized (_surfaceHolder) {
                    doDraw(canvas, isUpdate);
                }
            } finally {
                if (canvas != null) {
                    _surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }

后来我尝试将0,0,1,1传递给脏矩形。无法让它工作......

2 个答案:

答案 0 :(得分:0)

我在Android documentation中找到了这个有趣的注释:

  

在unlockCanvas()之间永远不会保留Surface的内容   和lockCanvas(),因此,Surface区域内的每个像素   必须写。这个规则的唯一例外是脏的时候   指定了矩形,在这种情况下,将使用非脏像素   保留。

所以要做你想做的事情,看起来你需要在lockCanvas电话中提供一个非空的脏矩形。此外,只有当您的节点像素都不相交时,这才会起作用。

答案 1 :(得分:0)

SurfaceView是双缓冲或三缓冲。之前的内容是"保留"从某种意义上说,系统并不是为了清除旧缓冲区,但你不能依赖这种行为。

如果指定了一个脏矩形,框架将呈现您提出的任何内容,然后从新缓冲区顶部的前一个缓冲区中复制非脏区域。

允许系统扩展脏矩形 - 可以更新传递给lockCanvas()的Rect。您需要重新绘制其中的每个像素。

对于这个(有点眼睛灼热)的例子,请参阅" TextureView中的简单画布"在Grafika

有关系统工作原理的详细信息,请参阅this article