Android:无法清除SurfaceView的初始绘图

时间:2015-03-13 05:49:33

标签: android graphics surfaceview

我刚开始玩开发Android应用程序并遇到了一些麻烦。

此测试应用程序的目的是在屏幕的右下方移动一个正方形。就这么简单。

MainActivity类(当前入口点)如下所示:

    Main Activity class (current entry point) looks like so:

    public class MainActivity extends Activity {
    Canvas canvas;
    GameLoopThread gameThread;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); //Super constructor
        gameThread=new GameLoopThread(); //Create GameLoop instance
        //Create mySurfaceView instance and pass it the new gameloop
        MySurfaceView sView=new MySurfaceView(this,gameThread);
        //Without this only the bit I cant remove is drawn
        sView.setBackgroundColor(Color.TRANSPARENT);
        setContentView(sView); //Set the current ContentView to the one we created
        //Pass the GameThread the MySurfaceView to repeatedly update
        gameThread.setSurfaceView(sView); 
        gameThread.start(); //Start the thread
    }
}

GameLoopThread看起来像这样:

public class GameLoopThread extends Thread {
protected volatile boolean running;
private MySurfaceView view;

public GameLoopThread(){
}

public void setSurfaceView(MySurfaceView view){
    this.view=view;
}

@Override
public void run() {
    running=true;
    while(running){
        Canvas c = null;
        c = view.getHolder().lockCanvas(); //Get the canvas
        if (c!=null) {
            synchronized (view) {
                view.draw(c); //Run the doDraw method in our MySurfaceView
            }
        }
        try {
            sleep(30, 0); //Throttle
        }
        catch(InterruptedException e){
            e.printStackTrace();
        }
        if (c != null) {
            view.getHolder().unlockCanvasAndPost(c); //Lock and post canvas
        }
    }
}

public void terminate(){
    running=false;
}

}

最后MySurfaceView看起来像这样:

public class MySurfaceView extends SurfaceView {
    private Bitmap bmp;
    private SurfaceHolder holder;
    private final GameLoopThread gameLoop;
    Paint paint;
    float x=0;
    float y=0;

    public MySurfaceView(Context c, GameLoopThread gThread){
        super(c);
        holder=getHolder();
        gameLoop=gThread;
        paint=new Paint();
        paint.setColor(Color.CYAN);
        paint.setStrokeWidth(10);
        holder.addCallback(new CallBack());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
        paint.setColor(paint.getColor() - 1);
        canvas.drawRect(x, y, x + 50, y + 50, paint);
        x++;
        y++;
    }

    private class CallBack implements SurfaceHolder.Callback{
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

            gameLoop.terminate();
            while (true) {
                try {
                    gameLoop.join();
                    break;
                } catch (InterruptedException e) {
                }
            }
        }
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format,
                                   int width, int height) {
        }
    }
}

问题 这一切都有效,除了最初的几个吸引到视图中的一个" stick"。它仍然是以后绘制的任何东西的顶部。见下文:

Overlap

我无法理解为什么会这样。没有任何清算可以解决问题。如果我不再画出新的'广场上的“卡住”#39;广场遗骸。你可以看到我改变了新的'的颜色。正方形,以测试它是否会改变“卡住”状态。一个表明它正在重绘的东西。显然它不是。

在每次抽奖之间暂停30ms时,不会为4个循环绘制任何内容,导致没有“卡住”#39;广场。在最初的4个结果之后开始绘制会产生一个在屏幕上移动的正方形。

改变暂停时间会改变必须等待的循环次数,但这种关系看起来并不成比例。

其他信息

这是在三星Galaxy SIII Mini上运行的

SDK verson 4.0.3

1 个答案:

答案 0 :(得分:1)

SurfaceView有两个部分,一个是Surface和一个View。当您使用lockCanvas()获得Canvas时,您将获得Surface部件的Canvas。 Surface是一个单独的图层,与用于所有View元素的图层无关。

您已经对SurfaceView进行了子类化并提供了onDraw()函数,View层次结构使用该函数渲染到View部分。我的猜测是View层次结构失效,并决定在SurfaceView的View部分上绘制。您跳过前几次循环迭代的渲染的实验是有效的,因为您正在跳过无效上发生的渲染。由于Surface图层是在View图层后面绘制的,因此您会看到onDraw() - 渲染的正方形位于您正在渲染的其他内容之上。

通常你不会在视图上画画;它只是一个透明的占位符,布局代码使用它来留下一个"洞"在Surface将显示的View图层中。

onDraw()重命名为doDraw(),然后删除@override。我认为根本没有将SurfaceView子类化的理由。这应该可以防止SurfaceView在其视图上绘制。

当然,如果你希望拥有一个遮​​罩层,也许是为了添加圆角或一个"污垢"效果,在视图上绘制是一种简单的方法来实现它。

有关完整故事,请参阅Graphics Architecture doc