2011-08-19 107 views
7

我有一個帶有開始按鈕的簡單屏幕。當按下「開始」按鈕時,我想要使用SurfaceView轉到新屏幕以顯示相機。在SurfaceView加載時顯示我的佈局相機預覽

一切工作正常,但相機需要一段時間才能加載,這給我一個黑屏。 我想要加載新的佈局。而不是啓動相機後它已被加載中...

爲此,我在後臺線程全部裝入相機了,不過,我得到一個黑色的屏幕... 這裏是我的佈局:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout android:id="@+id/RelativeLayout1" 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:background="@drawable/blue_bg"> 

    <SurfaceView 
     android:id="@+id/surface_camera" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:layout_marginLeft="25dp" 
     android:layout_marginRight="25dp" 
     android:layout_below="@id/scan_header" 
     android:layout_above="@id/scan_footer"> 
    </SurfaceView> 

</RelativeLayout> 

這裏是我的活動,它加載新視圖的方法:

private void setContent() 
{ 
    setContentView(R.layout.scan) 

    Thread t = new Thread() 
    { 
     public void run() 
     { 

      final SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera); 
      final SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder(); 

      try 
      { 
       cameraView = new CameraView(); 
       mSurfaceHolder.addCallback(cameraView); 
       cameraView.setPictureListener(SunpluggedActivity.this); 
       mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

      } catch(Exception e) 
      { 
       Log.d(TAG, "Another exception"); 
       e.printStackTrace(); 
      } 
     } 
    }; 
    t.start(); 
} 

怎麼來的,新的佈局沒有顯示,直到線程已經完成加載攝像頭?

編輯:我在線程中嘗試了Thread.sleep(200)休眠一段時間。當我做到這一點,新的佈局immedeately顯示,但相機從未開始......

回答

20

好的,問題是我在xml佈局中使用了我的SurfaceView。 你調用的那一刻:setContentView(your_layout) - > XML文件被誇大了。 這意味着,SurfaceView也會膨脹。這又意味着SurfaceView onSurfaceCreated方法被調用,這觸發打開相機等。

因此,這整個過程需要一段時間,因此,您以前的活動(例如啓動與SurfaceView的活動)似乎沒有反應...

我的解決方案,在BG線程中創建CameraView解決了無法響應。但未能在SurfaceView中顯示相機輸出。

解決方案是從您的XML中刪除您的SurfaceView。這會立即開始你的活動(因爲SurfaceView &相機沒有實例化)。 加載新的「活動」佈局後,可以以編程方式將新的SurfaceView添加到屏幕。當然,這也需要花費時間,但是您的UI會快速切換到新的活動,並且您可以在SurfaceView和相機加載的同時顯示加載器!

SO:刪除SURFACEVIEW從XML - >添加IT編程: 發射活動:

public class Launch extends Activity implements OnClickListener 
{ 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     Button btn = (Button)findViewById(R.id.button1); 
     btn.setOnClickListener(this); 
    } 

    @Override 
    public void onClick(View v) { 
     Intent intent = new Intent(Launch.this, SurfaceTestActivity.class); 
     startActivity(intent); 
    } 
} 

的main.xml(只需一個按鈕,啓動新的活動)

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout android:id="@+id/RelativeLayout1" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="#ff6600"> 

    <Button 
     android:id="@+id/button1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Button" /> 
</RelativeLayout> 

這裏的第二個活動(其中包含SurfaceView)

public class SurfaceTestActivity extends Activity { 

    private Context mContext; 
    private CameraView cameraView; 
    private Handler mHandler = new Handler(); 
    private final Runnable mLoadCamera = new Runnable() 
    { 
     public void run() 
     { 
      startCamera(); 
     } 
    }; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContent(); 
     mContext = getApplicationContext(); 
    } 

    private void startCamera() 
    { 
     RelativeLayout rl = (RelativeLayout)findViewById(R.id.surface_camera); 
     SurfaceView surfaceView = new SurfaceView(mContext); 
     final SurfaceHolder mSurfaceHolder = surfaceView.getHolder(); 

     try 
     { 
      cameraView = new CameraView(); 
      mSurfaceHolder.addCallback(cameraView); 
      mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     } catch(Exception e) 
     { 
      Log.d("debug", "Another exception"); 
      e.printStackTrace(); 
     } 

     if(rl != null && surfaceView != null) 
      rl.addView(surfaceView); 
    } 

    private void setContent() 
    { 
     setContentView(R.layout.scan); 

     // Post the Runnable with a Slight delay -> than your layout will be 
     // shown. Without the delay -> your UI will feel inresponsive 
     mHandler.postDelayed(mLoadCamera, 100); 
    } 
} 

這裏是t他第二次活動的佈局(無SURFACEVIEW)

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout android:id="@+id/RelativeLayout1" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:background="#ff6600"> 
    <RelativeLayout 
     android:id="@+id/header" 
     android:layout_width="fill_parent" android:layout_height="wrap_content"> 
     <TextView 
      android:layout_width="wrap_content" android:layout_height="wrap_content" 
      android:text="Explanation Txt"></TextView> 
    </RelativeLayout> 
    <RelativeLayout 
     android:id="@+id/footer" 
     android:layout_width="fill_parent" android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true"> 
     <TextView 
      android:layout_width="wrap_content" android:layout_height="wrap_content" 
      android:text="Explanation Txt"></TextView> 
    </RelativeLayout> 

    <RelativeLayout 
     android:id="@+id/surface_camera" 
     android:layout_width="fill_parent" 
     android:layout_height="match_parent" 
     android:layout_above="@+id/footer" 
     android:layout_below="@+id/header" 
     android:background="#ff0066"> 

    </RelativeLayout> 

</RelativeLayout> 

最後,完成了答案,這裏是爲CameraView()的代碼。它實際上只是一個簡單的實現來打開相機和顯示內容:

public class CameraView implements SurfaceHolder.Callback{ 

    // Variables 
    private Camera mCamera = null; 
    private boolean mPreviewRunning = false; 
    private boolean mProcessing = false; 
    private int mWidth = 0; 
    private int mHeight = 0; 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) 
    { 
     if(mPreviewRunning) 
     { 
      mCamera.stopPreview(); 
     } 

     // Store width and height 
     mWidth = width; 
     mHeight = height; 

     // Set camera parameters 
     Camera.Parameters p = mCamera.getParameters(); 
     mCamera.setParameters(p); 

     if(android.os.Build.VERSION.SDK_INT >= 8) 
     { // If API >= 8 -> rotate display... 
      mCamera.setDisplayOrientation(90); 
     } 

     try 
     { 
      mCamera.setPreviewDisplay(holder); 
     } catch(IOException e) 
     { 
      e.printStackTrace(); 
     } 

     mCamera.startPreview(); 
     mPreviewRunning = true; 

    } 

    @Override 
    public void surfaceCreated(final SurfaceHolder holder) 
    { 
     try { 
      mCamera = Camera.open(); 
      mCamera.setPreviewDisplay(holder); 
     } catch (IOException e) 
     { 
      mCamera.release(); 
      mCamera = null; 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     if(mCamera != null) 
     { 
      mCamera.setPreviewCallback(null); 
      mCamera.stopPreview(); 
      mCamera.setPreviewCallback(null); 
      mPreviewRunning = false; 
      mCamera.release(); 
      mCamera = null; 
     } 
    } 
} 
+2

Android Developers指南還建議在WorkerThread中調用Camera.open()以避免阻塞UI線程。 –

+1

這段代碼工作得非常好......如果我想在其上添加我的佈局,該怎麼辦? –

+1

在xml中,創建一個包含surfaceview的相關佈局。這個surfaceView將是你的'相機'視圖。最重要的是,你可以添加所有的佈局。 – Entreco