Note that there are some explanatory texts on larger screens.

plurals
  1. POAndroid SurfaceView not creating in Portrait Mode
    primarykey
    data
    text
    <p>I've got a simple LinearLayout with a custom SurfaceView class and some buttons. Previously I had forced the orientation to Landscape in the Activity tag in the Manifest, however now I need to make it portrait. For some reason when I force the orientation portrait the SurfaceView isn't created. I tested the layout by just using a single FrameLayout and inside that a single instance of my SurfaceView class but still, it wouldn't create properly.</p> <p>The error I get depends on what the first instance to the Thread within the SurfaceView is. Normally it's my UI thread in onCreate requesting a handle to the thread which causes a NullPointerException.</p> <p>Any ideas why my code works in landscape but not portrait? Also it has the same issue if I don't select the orientation and then rotate it from landscape to portrait.</p> <p>EDIT: Here's my layout:</p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"&gt; &lt;stu.test.project.DrawingSurface android:layout_width="fill_parent" android:layout_height="700dp" android:id="@+id/drawingSurface"/&gt; &lt;LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"&gt; &lt;LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:id="@+id/ButtonRow1"/&gt; &lt;LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:id="@+id/ButtonRow2"/&gt; &lt;/LinearLayout&gt; &lt;/LinearLayout&gt; </code></pre> <p>Here's the onCreate on the Activity that calls the surfaceView, the error is located on the last line where the handle to the Thread is retrieved</p> <pre><code>public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.drawing_layout); // Retrieve STATE and patient number from intent bundle = this.getIntent().getExtras(); STATE = bundle.getInt("state"); patientString = bundle.getString("patientString"); //retrieveViews(); showButtons(); System.out.println("IN ONCREATE"); // Setup initial stuff if creating rather than resuming if (savedInstanceState==null){ System.out.println("IN ONCREATE AND NO SIS"); switch(STATE){ case STATE_DRAW: setupDraw(); break; case STATE_LOAD: setupLoad(); drawLoad(); break; } } /* Should put Else in here * to maybe resume data from savedInstanceState * rather than using onSurfaceCreated as do at moment */ // Retrieve handle to thread mThread = drawingSurface.getThread(); } </code></pre> <p>And here's the SurfaceView Class, not sure what is relevant so copied it all:</p> <pre><code>public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback { private boolean _run; private Object mPauseLock = new Object(); private boolean mPaused; private int STATE; private static final int STATE_DRAW=1; private static final int STATE_LOAD=2; private static final int STATE_PAUSED=4; private static final int STATE_RESUME_DRAWING=5; private boolean finishDrawing; private boolean startedDrawing=true; private int resetCanvas=0; private boolean threadRunning; protected DrawThread thread; boolean loaded; public DrawingSurface(Context context, AttributeSet attrs) { super(context, attrs); getHolder().addCallback(this); thread = new DrawThread(getHolder()); } class DrawThread extends Thread{ private SurfaceHolder mSurfaceHolder; private List&lt;DrawingPath&gt; mDrawingPaths; private List&lt;MyLine&gt; mMyLines, backupLines; private Paint mPaint; public DrawThread(SurfaceHolder surfaceHolder){ mSurfaceHolder = surfaceHolder; mDrawingPaths = Collections.synchronizedList(new ArrayList&lt;DrawingPath&gt;()); mMyLines = Collections.synchronizedList(new ArrayList&lt;MyLine&gt;()); } public void setRunning(boolean run) { _run = run; } public void setBackupLine(List&lt;MyLine&gt; l){ backupLines = l; System.out.println("SETUP BACKLINE SIZE IS: "+backupLines.size()); } // Two methods for your Runnable/Thread class to manage the Thread properly. public void onPause() { synchronized (mPauseLock) { // Only pause if not finished drawing, if finished want to exit thread if (!finishDrawing){ mPaused = true; loaded=false; } } System.out.println("Set mPaused = true"); } public void onResume() { synchronized (mPauseLock) { mPaused = false; mPauseLock.notifyAll(); } System.out.println("Set mPaused = false"); // // Load the saved drawings or reload // if (STATE == STATE_DRAW) // setState(STATE_RESUME_DRAWING); // // If loading then dont change state and instead just restart thread // else if (STATE == STATE_LOAD){ //// resumeDrawing(); // setRunning(true); // } } public boolean needToWait(){ return finishDrawing||mPaused; } public void setFinishDrawing(boolean b){ finishDrawing=b; } public void setReset(int reset){ resetCanvas=reset; } public void addMyLines(List&lt;MyLine&gt; lines){ mMyLines = lines; } public void addDrawingPath(DrawingPath drawingPath){ mDrawingPaths.add( drawingPath ); } public int getSizeDrawingPaths(){ return mDrawingPaths.size(); } public void setLoadPaint(Paint p){ mPaint = p; } public DrawingPath getDrawingPath(int index){ return mDrawingPaths.get(index); } @Override public void run() { while (_run){ // Set variable for running threadRunning=true; Canvas canvas = null; // This code pauses the thread synchronized (mPauseLock) { while (mPaused) { try { mPauseLock.wait(); System.out.println("IN PAUSE LOOP"); } catch (InterruptedException e) { } } } try{ canvas = mSurfaceHolder.lockCanvas(null); // Split into DRAW and LOAD // DRAW IMAGE FROM PATHS if (STATE == STATE_DRAW){ synchronized(mDrawingPaths) { // If not finished drawing or resetthen draw onto canvas if (!finishDrawing&amp;&amp;resetCanvas==0){ // // Draw screen white // if (startedDrawing){ // startedDrawing=false; // canvas.drawColor(Color.WHITE); // System.out.println("DRAWING CANVAS WHITE"); // // } doDraw(canvas); } } if (resetCanvas&gt;0){ System.out.println("Resetting canvas"); if (canvas!=null) canvas.drawColor(Color.WHITE); resetCanvas--; } } // DRAW IMAGE FROM POINTS else if (STATE == STATE_LOAD){ doLoad(canvas, mMyLines); // Then close the thread setRunning(false); } // IF RESUMING FROM DRAWING PAUSE else if (STATE == STATE_RESUME_DRAWING){ if (!loaded) { doLoad(canvas, backupLines); System.out.println("DID LOAD OF RESUME"); setState(STATE_DRAW); loaded=true; //setRunning(false); } } } finally { if (canvas!=null){ mSurfaceHolder.unlockCanvasAndPost(canvas); } } } // While run } public void doDraw(Canvas c){ @SuppressWarnings("rawtypes") Iterator i = mDrawingPaths.iterator(); while (i.hasNext()){ final DrawingPath drawingPath = (DrawingPath) i.next(); if (c==null) System.out.println("CANVAS IS NULL"); else if (drawingPath.path==null) System.out.println("PATH IS NULL"); else if (drawingPath.paint==null) System.out.println("PAINT IS NULL"); if (c!=null) // Only draw to canvas if it isnt null c.drawPath(drawingPath.path, drawingPath.paint); } } public void doLoad(Canvas c, List&lt;MyLine&gt; lines){ // Loop through the List of lines @SuppressWarnings("rawtypes") Iterator i = lines.iterator(); while(i.hasNext()){ // Get the current line final MyLine lineIt = (MyLine) i.next(); // Create new array of floating points to hold the PointFs from MyLine to draw float prevX=0, prevY=0; for (int j=0;j&lt;lineIt.getSize()-1;j=j+2){ if (c==null) System.out.println("CANVAS IS NULL"); if (j!=0&amp;&amp;c!=null){ c.drawLine(prevX, prevY, lineIt.getPoint(j).x, lineIt.getPoint(j+1).y, mPaint); } prevX = lineIt.getPoint(j).x; prevY = lineIt.getPoint(j+1).y; } } } public void remove(int i) { mDrawingPaths.remove(i); } public void clearAllPaths(){ mDrawingPaths.clear(); } public void setState(int s){ STATE = s; } } public void addDrawingPath (DrawingPath drawingPath){ thread.addDrawingPath(drawingPath); } public int getSizeDrawingPaths(){ return thread.getSizeDrawingPaths(); } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } public void surfaceCreated(SurfaceHolder holder) { // only create thread if doesnt exist if (!threadRunning){ thread.setRunning(true); thread.setFinishDrawing(false); thread.setReset(2); // Set reset to colour screen white thread.start(); } // // Resuming is handled in DrawingActivity's onPause override // else { // thread.onResume(); // } } public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub boolean retry = true; // If finished drawing then close thread // Else just want to pause thread // if (finishDrawing){ // thread.setRunning(false); // while (retry) { // try { // thread.join(); // retry = false; // threadRunning = false; // Set threadRunning to false so creates new thread when rejoins // } catch (InterruptedException e) { // // we will try it again and again... // } // } // } // else { // thread.onPause(); // System.out.println("Paused thread in SurfaceDestroyed"); // System.out.println("threadRunning is :"+threadRunning); // } } public void remove(int i) { thread.remove(i); } public void getDrawingPath(int i){ thread.getDrawingPath(i); } public void clearAllPaths(){ thread.clearAllPaths(); } public void resetScreen(){ thread.setReset(2); } public void addMyLines(List&lt;MyLine&gt; lines){ thread.addMyLines(lines); } public void finishDrawing(){ thread.setFinishDrawing(true); } public DrawThread getThread(){ return thread; } public void resumeDrawing(){ thread.setFinishDrawing(false); } public void setState(int s){ thread.setState(s); } public void setLoadPaint(Paint p){ thread.setLoadPaint(p); } public void pauseThread(){ thread.onPause(); } public void resumeThread(){ thread.onResume(); } public boolean getThreadRunning(){ return threadRunning; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload