2011-08-19 13 views
7

Tengo una pantalla simple con un botón de inicio. Cuando se presiona el botón de inicio, quiero ir a una nueva pantalla con un SurfaceView para mostrar la cámara.Mostrar mi diseño mientras se carga SurfaceView Vista previa de la cámara

Todo funciona bien, pero la cámara tarda un poco en cargarse, y esto me da una pantalla en negro. Me gustaría que se cargue el nuevo diseño. Y que inicia la cámara después de que se haya cargado ...

para ello, hago toda la carga de la cámara en un subproceso en segundo plano, pero aún así, me sale una pantalla en negro ... Aquí está mi diseño:

<?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> 

Aquí es el método de mi actividad, que carga el nuevo punto de vista:

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

¿Cómo es que, no se muestra el nuevo diseño, hasta que el mensaje ha terminado de cargar la cámara?

EDIT: He intentado Thread.sleep (200) dentro del Tema a dormir durante algún tiempo ... Cuando hago eso, el nuevo diseño se muestra immedeately, pero la cámara nunca comienza ...

Respuesta

20

Muy bien, el problema es que utilicé mi SurfaceView dentro del diseño xml. En el momento en que llama: setContentView (your_layout) -> el archivo XML está inflado. Eso significa que SurfaceView también está inflado. Eso, una vez más, significa que se llama SurfaceView onSurfaceCreated Methods, que activa la apertura de la cámara, etc.

Por lo tanto, todo este proceso lleva tiempo, por lo tanto, su actividad anterior (por ejemplo, el inicio de la actividad con SurfaceView) parece para que no responda ...

Mi solución para crear CameraView en un hilo BG resuelve la respuesta. Pero no se pudo mostrar la salida de la cámara en SurfaceView.

La solución es eliminar su SurfaceView de su xml. Esto iniciará su actividad de forma inmediata (ya que la cámara SurfaceView & no se crea una instancia). Una vez que haya cargado su nuevo diseño de Actividades, puede agregar mediante programación un nuevo SurfaceView a su pantalla. Por supuesto, esto también lleva tiempo, pero tu UI cambia a la nueva actividad rápidamente, ¡y puedes mostrar un cargador mientras SurfaceView y Camera se están cargando!

SO: REMOVER LA SurfaceView del XML -> ADD mediante programación: lanzamiento Actividad:

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 (sólo un botón para iniciar la nueva actividad)

<?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> 

Aquí es la segunda actividad (que contiene el 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); 
    } 
} 

Y aquí está t l segundo diseño de Actividad (SIN 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> 

Por último, para completar la respuesta, aquí está el código para el ángulo de cámara().Realmente es sólo una implementación sencilla de conseguir abrir la cámara y mostrar el contenido:

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

La guía de desarrolladores de Android también recomienda llamar Camera.open() en WorkerThread para evitar el bloqueo del hilo de interfaz de usuario. –

+1

Este código funciona perfectamente bien ... ¿y si quiero agregar mi diseño encima? –

+1

En xml, crea un diseño relativo con una vista de superficie en él. Esta vista de superficie será su vista de "cámara". Además de eso, puedes agregar todos tus diseños. – Entreco

Cuestiones relacionadas