【问题标题】:Android SurfaceView not creating in Portrait ModeAndroid SurfaceView 不在纵向模式下创建
【发布时间】:2012-02-03 12:35:42
【问题描述】:

我有一个带有自定义 SurfaceView 类和一些按钮的简单 LinearLayout。以前我在 Manifest 的 Activity 标记中强制将方向设置为横向,但是现在我需要将其设为纵向。出于某种原因,当我强制定向纵向时,不会创建 SurfaceView。我只使用一个 FrameLayout 并在里面测试了我的 SurfaceView 类的一个实例,但它仍然无法正确创建。

我得到的错误取决于 SurfaceView 中线程的第一个实例是什么。通常是我在 onCreate 中的 UI 线程请求导致 NullPointerException 的线程句柄。

任何想法为什么我的代码在横向而不是纵向工作?如果我不选择方向然后将其从横向旋转到纵向,也会出现同样的问题。

编辑:这是我的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <stu.test.project.DrawingSurface
        android:layout_width="fill_parent"
        android:layout_height="700dp"
        android:id="@+id/drawingSurface"/>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">   
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:id="@+id/ButtonRow1"/>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:id="@+id/ButtonRow2"/>
    </LinearLayout>
</LinearLayout>

这里是调用surfaceView的Activity上的onCreate,错误位于检索到Thread的句柄的最后一行

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();

      }

这里是 SurfaceView 类,不确定什么是相关的,所以全部复制:

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<DrawingPath> mDrawingPaths;
    private List<MyLine> mMyLines, backupLines;
    private Paint mPaint;

    public DrawThread(SurfaceHolder surfaceHolder){
        mSurfaceHolder = surfaceHolder;
        mDrawingPaths = Collections.synchronizedList(new ArrayList<DrawingPath>());
        mMyLines = Collections.synchronizedList(new ArrayList<MyLine>());
    }

    public void setRunning(boolean run) {
        _run = run;
    }

    public void setBackupLine(List<MyLine> 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<MyLine> 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&&resetCanvas==0){
 //                         // Draw screen white
//                          if (startedDrawing){
//                              startedDrawing=false;
//                              canvas.drawColor(Color.WHITE);
//                              System.out.println("DRAWING CANVAS WHITE");
//                              
//                          }
                        doDraw(canvas);
                    }
                    }
                    if (resetCanvas>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<MyLine> 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<lineIt.getSize()-1;j=j+2){  
                 if (c==null)
                    System.out.println("CANVAS IS NULL");
                if (j!=0&&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<MyLine> 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;
    }
}

【问题讨论】:

  • 你能把你的一些代码贴出来,让我们看看可能是什么问题吗?
  • 贴出我的布局,部分Activity和所有SurfaceView代码。
  • 上一个Activity,用SurfaceView调用这个Activity的也是强制横向的。我发现如果我允许之前的 Activity 是纵向的,那么当这个 Activity 启动时,SurfaceView 就会按要求工作。所以问题出在启动此活动时屏幕改变方向的某个地方。

标签: android layout orientation surfaceview


【解决方案1】:

纵向和横向的布局文件是否相同?

我今天遇到了一个类似的 buglet,我在纵向布局文件中有surfaceView,但在横向布局文件中没有。出于某种原因,它运行了,但是当我旋转设备时,surfaceCreated|Changed|Destroyed 不再发生。转回来,一切又恢复了快乐。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-22
    • 1970-01-01
    相关资源
    最近更新 更多