0

我正在试验 SurfaceView。我的要求是首先简单地渲染一个节点(简单的可绘制)。然后,在稍后的时间点渲染更多节点。

我的线程的 run 方法和我的 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 传递给脏矩形。还不能让它工作......

4

2 回答 2

0

我在 Android文档中发现了这个有趣的注释:

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

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

于 2014-05-13T03:45:51.217 回答
0

SurfaceView 是双缓冲或三缓冲的。从某种意义上说,以前的内容是“保留”的,系统不会特意清除旧缓冲区,但您不能依赖这种行为。

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

允许系统扩展脏矩形——您传递给的 RectlockCanvas()可能会被更新。您需要重绘其中的每个像素。

有关此操作的(有些令人眼花缭乱的)示例,请参阅 Grafika 中的“ TextureView中的简单画布” 。

有关系统如何工作的更多详细信息,请参阅这篇文章

于 2014-05-13T05:03:13.563 回答