I will try to formulate a normal question. I have a simple application, but for this question I have simplified everything more to focus on the root of the problem. The essence of the application is a part of the screen, in my case it is SurfaceView , where dynamically after each button click a geometric shape should appear and with each click should be more. I did this, but I had a problem. I have already cut as much as possible everything I could in the functional, in order to understand where the bug is and still do not understand why I have three such SurfaceView (and it’s not even clear to me why three), which in turn, after pressing the button, change, although I should only have one SurfaceView . This leads to the fact that I have three different sets of shapes that are filled in turn, instead of one. The first SurfaceView is created in green: mCanvas.drawColor(Color.GREEN); . Further, I don’t know why, after clicking the button, I SurfaceView another SurfaceView that I understand and the screen goes black. After the new click is the same (the third SurfaceView ), the fourth click again returns to green and again through the cycle. I understand perfectly well that the problem is in two lines in the listener for the button (marked with a comment), but I just can not understand what the error is ...

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); hideActionBar(); initView(); mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { mCanvas = null; mSurfaceHolder = null; mSurfaceHolder = mSurfaceView.getHolder(); mCanvas = mSurfaceHolder.lockCanvas(); mCanvas.drawColor(Color.GREEN); mSurfaceHolder.unlockCanvasAndPost(mCanvas); } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } }); mRectangleButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Проблема тут! mCanvas = mSurfaceHolder.lockCanvas(); // drawRectangle(); mSurfaceHolder.unlockCanvasAndPost(mCanvas); } }); } } 

    2 answers 2

    Place inside

    surfaceCreated() surfaceDestroyed() surfaceChanged()

     Log.E("surfaceCreated", "OK") 

    And look at the Logs after pressing a button; So we will know if these methods are called after mSurfaceHolder.lockCanvas();

    • Well, these methods do not depend on the buttons. The first method is called when the Activity is started, the second one is also called immediately, and the third during closing. I partially understood what my problem was. This is the buffering of the View components and there are just two buffers there. I was able to fix the code a bit based on this answer: stackoverflow.com/questions/36266994/… But still, a black screen appears, although all the figures are already on the common canvas. - Kostya Bakay

    I figured out the problem. The bottom line is that SurfaceView uses multiple buffers. It was those two black screens that were those buffers. In order to avoid this problem you need to use one trick with a Bitmap . This is what the updated listener code looks like for the button (there are more lines of code for realizing this listener here - they are not necessary, but I left them for a better understanding).

      mRectangleButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mScreenBitmap == null) return; Canvas canvas = new Canvas(mScreenBitmap); if (mShapeFactory == null) mShapeFactory = new ShapeFactory(getApplicationContext()); Shape shape = mShapeFactory.getShape(getApplicationContext(), "rectangle"); mVector.add(shape); shape.draw(canvas); canvas = mSurfaceHolder.lockCanvas(null); canvas.drawBitmap(mScreenBitmap, 0, 0, null); mSurfaceHolder.unlockCanvasAndPost(canvas); mRectangleCount++; Log.d(TAG, "Rectangle:" + mRectangleCount); updateShapeCount(); } }); 

    For more detailed information, it’s worthwhile to read the theoretical answer to this question, and I took a sample code to solve the problem from the answer to this question.