title: Android Multiple SurfaceViews
body: <p>I'm trying to work with 3 SurfaceViews on one screen, one on top half (BoardView), one on bottom half (StatusView), and the last one as an extra layer above the top half (TileView) (see main.xml).</p>
  
  <p>I created a class MySurfaceView, which is extended by BoardView, StatusView and TileView.</p>
  
  <p>I've got multiple problems with this.</p>
  
  <p>Let me first give the code.</p>
  
  <p>main.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:background="@color/main_background"&gt;
  
      &lt;com.niek.test.BoardView
          android:id="@+id/boardview"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" /&gt;
  
      &lt;FrameLayout
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:layout_below="@+id/boardview"&gt;
          &lt;com.niek.test.StatusView
              android:id="@+id/statusview"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:background="#F0931E"
              android:layout_below="@+id/boardview" /&gt;
  
              &lt;com.niek.test.TileView
                  android:id="@+id/tileview"
                  android:layout_width="180dip"
                  android:layout_height="60dip"
                  android:layout_gravity="bottom"/&gt;
  
  
      &lt;/FrameLayout&gt;
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>MainActivity.java:</p>
  
  <pre><code>package com.niek.test;
  
  public class MainActivity extends Activity {
  
      private Board board;
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
  
          board = new Board();
          BoardView boardView = (BoardView) findViewById(R.id.boardview);
          boardView.setBoard(board);
          StatusView statusView = (StatusView) findViewById(R.id.statusview);
          statusView.setBoard(board);
      }
  }
  </code></pre>
  
  <p>MySurfaceView.java</p>
  
  <pre><code>package com.niek.test;
  
  public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
  
      protected DrawThread drawThread;
  
      public MyView(Context context, AttributeSet attrs) {
          super(context, attrs);
          getHolder().addCallback(this);
          setFocusable(true);
  
          drawThread = new DrawThread(getHolder());
      }
  
      @Override
      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
          // TODO Auto-generated method stub
  
      }
  
      @Override
      public void surfaceCreated(SurfaceHolder holder) {
          // TODO Auto-generated method stub
          drawThread.setRunning(true);
          drawThread.start();
      }
  
      @Override
      public void surfaceDestroyed(SurfaceHolder holder) {
          // we have to tell thread to shut down &amp; wait for it to finish, or else
          // it might touch the Surface after we return and explode
          boolean retry = true;
          drawThread.setRunning(false);
          while (retry) {
              try {
                  drawThread.join();
                  retry = false;
              } catch (InterruptedException e) {
                  // we will try it again and again...
              }
          }
      }
  
      protected class DrawThread extends Thread {
          private SurfaceHolder surfaceHolder;
          private boolean isRunning;
  
          public DrawThread(SurfaceHolder surfaceHolder) {
              this.surfaceHolder = surfaceHolder;
              isRunning = false;
          }
  
          public void setRunning(boolean run) {
              isRunning = run;
          }
  
          public void run() {
              Canvas c;
              while (isRunning) {
                  try {
                      Thread.sleep(100);
                  } catch (Exception e) {
                      // TODO: handle exception
                  }
                  c = null;
                  try {
                      c = surfaceHolder.lockCanvas(null);
                      synchronized (surfaceHolder) {
                          onDraw(c);
                          postInvalidate();
                      }
                  } finally {
                      // do this in a finally so that if an exception is thrown
                      // during the above, we don't leave the Surface in an
                      // inconsistent state
                      if (c != null) {
                          surfaceHolder.unlockCanvasAndPost(c);
                      }
                  }
              }
          }
      }
  
  }
  </code></pre>
  
  <p>These three classes extend MySurfaceView:</p>
  
  <p>BoardView.java</p>
  
  <pre><code>package com.niek.test;
  
  
  public class BoardView extends MySurfaceView {
  
      private int squareSize, marginX, marginY;
  
      private Board board;
  
      Paint boardBorder;
  
      public BoardView(Context context, AttributeSet attrs) {
          super(context, attrs);
          board = null;
      }
  
      public void setBoard(Board board) {
          this.board = board;
      }
  
      private void init(SurfaceHolder holder) {
          Canvas canvas = null;
          try {
              canvas = holder.lockCanvas();
              /* Initialize the board */
              squareSize = canvas.getWidth() / Board.GRIDSIZE;
  
              /* Size the view */
              LayoutParams lp = getLayoutParams();
              lp.height = (squareSize * Board.GRIDSIZE) + 4;
              setLayoutParams(lp);
  
              /* Place the board neatly in the center */
              marginX = (canvas.getWidth() - (squareSize * Board.GRIDSIZE)) / 2;
              marginY = 1;
          } finally {
              holder.unlockCanvasAndPost(canvas);
          }
  
          boardBorder = new Paint();
          boardBorder.setColor(Color.RED);
          boardBorder.setStyle(Style.STROKE);
      }
  
      @Override
      public void onDraw(Canvas canvas) {
          drawBoard(board, canvas);
      }
  
      @Override
      public void surfaceCreated(SurfaceHolder holder) {
          init(holder);
          super.surfaceCreated(holder);
      }
  
      private void drawBoard(Board board, Canvas canvas) {
          synchronized (board) {
              if (board != null) {
                  for (Square[] ys : board.getSquares()) {
                      for (Square xs : ys) {
                          xs.onDraw(canvas, squareSize, squareSize, marginX, marginY);
                      }
                  }
              }   
              canvas.drawRect(marginX - 1, marginY - 1, marginX + squareSize * Board.GRIDSIZE + 1, marginY + squareSize * Board.GRIDSIZE + 1, boardBorder);
          }
      }
  }
  </code></pre>
  
  <p>StatusView.java</p>
  
  <pre><code>package com.niek.test;
  
  public class StatusView extends MySurfaceView {
  
      private Board board;
      private Paint textPaint;
  
      public StatusView(Context context, AttributeSet attrs) {
          super(context, attrs);
          board = null;
  
          textPaint = new Paint();
          textPaint.setColor(Color.BLACK);
          textPaint.setTextSize(20);
          textPaint.setTypeface(Typeface.DEFAULT_BOLD);
      }
  
      public void setBoard(Board board) {
          this.board = board;
      }
  
      int tmp=0;
      @Override
      public void onDraw(Canvas c) {
          if (board != null) {
              c.drawText(tmp+"", 10, 20, textPaint);          
              tmp++;
              System.out.println(tmp);
          }
      }
  }
  </code></pre>
  
  <p>TileView.java</p>
  
  <pre><code>package com.niek.test;
  
  public class TileView extends MySurfaceView {
  
      public TileView(Context context, AttributeSet attrs) {
          super(context, attrs);
          System.out.println(0);
      }
  
  
      int tmp =0;
      @Override
      public void onDraw(Canvas c) {
          System.out.println(2);
          Paint p= new Paint();
          p.setColor(Color.RED);
          c.drawColor(Color.RED);
          c.drawText(tmp+"",10,10,p);
          tmp++;
  
      }
  
  }
  </code></pre>
  
  <p>Now what are my problems?</p>
  
  <p>First off, as you can see in MySurfaceView I've got this:</p>
  
  <pre><code>try {
      c = surfaceHolder.lockCanvas(null);
      synchronized (surfaceHolder) {
          onDraw(c);
          postInvalidate();
      }
  }
  </code></pre>
  
  <p>When I only use onDraw(c), only the BoardView gets drawn, the StatusView doesn't get drawn, but the tmp increments in the onDraw of StatusView are being executed.
  When I only use postInvalidate(), same story, but only StatusView gets drawn, BoardView doesn't.
  So that's why I use both methods, and both Views get drawn.</p>
  
  <p>Then there's TileView, the System.out(2) is being shown in logcat, but the view doesn't get drawn. It is a black square instead of the red square I ask it to be in the onDraw method.</p>
  
  <p>When I turn the screen off and then on again, the TileView does get drawn, and the tmp increments are shown.</p>
  
  <p>Who can help me?</p>
  
  <p>For clarity, I've created this based on <a href="http://www.droidnova.com/playing-with-graphics-in-android-part-ii,160.html" rel="noreferrer">this</a> tutorial.</p>