在SurfaceView加载时显示我的布局相机预览

问题描述:

我有一个带有开始按钮的简单屏幕。当按下“开始”按钮时,我想要使用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显示,但相机从未开始......

好的,问题是我在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