2011-08-19 4 views
7

J'ai un écran simple avec un bouton de démarrage. Lorsque le bouton Démarrer est pressé, je veux aller à un nouvel écran avec un SurfaceView pour montrer l'appareil photo.Afficher ma mise en page pendant le chargement de SurfaceView

Tout fonctionne très bien, mais la caméra prend un certain temps à charger, ce qui me donne un écran noir. Je voudrais charger la nouvelle mise en page. Et que de commencer l'appareil photo après qu'il a été chargé ...

cet effet, je fais tout le chargement de l'appareil photo dans un fil d'arrière-plan, mais toujours, je reçois un écran noir ... Voilà ma mise en page:

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

Voici la méthode de mon activité, qui charge la nouvelle vue:

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

Comment venir, la nouvelle disposition n'apparaît pas, jusqu'à ce que le fil a fini de charger l'appareil photo?

EDIT: J'ai essayé Thread.sleep (200) dans le fil de dormir pendant un certain temps ... Quand je fais cela, la nouvelle mise en page est affichée immedeately, mais la caméra ne commence jamais ...

Répondre

20

D'accord, le problème est que j'ai utilisé mon SurfaceView dans la mise en page xml. Le moment de l'appel: setContentView (your_layout) -> le fichier XML est gonflé. Cela signifie que le SurfaceView est également gonflé. Cela signifie que les méthodes SurfaceView onSurfaceCreated sont appelées, ce qui déclenche l'ouverture de la caméra, etc.

Donc, tout ce processus prend du temps, donc votre activité précédente (par exemple celle qui lance l'activité avec SurfaceView) semble pour ne pas répondre ...

Ma solution, de créer le CameraView dans un thread BG résout l'inresponsiveness. Mais n'a pas réussi à afficher la sortie Camera dans SurfaceView.

La solution est d'enlever votre SurfaceView de votre xml. Cela va commencer votre activité immédiatement (puisque les caméras SurfaceView & ne sont pas instanciées). Une fois votre nouvelle mise en page Activités chargée, vous pouvez ajouter un nouveau SurfaceView à votre écran par programmation. Bien sûr, cela prend du temps, mais votre interface utilisateur passe rapidement à la nouvelle activité, et vous pouvez afficher un chargeur pendant le chargement de SurfaceView et Camera!

SO: RETIRER LE SURFACEVIEW DE LA XML -> ADDITIONNEZ Programatically: Activité de lancement:

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 (juste un bouton pour lancer la nouvelle activité)

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

Voilà la deuxième activité (qui contient le 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); 
    } 
} 

Et voici t il seconde mise en page de l'activité (SANS 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> 

Enfin, pour compléter la réponse, voici le code pour le CameraView().Il est vraiment juste une implémentation simple pour obtenir ouvrir l'appareil photo et afficher le contenu:

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

Le guide Développeurs Android recommande également appeler Camera.open() dans WorkerThread pour éviter de bloquer l'interface utilisateur fil. –

+1

Ce code fonctionne parfaitement bien ... et si je veux ajouter ma mise en page? –

+1

En XML, créez un relativelayout avec une vue de surface. Cette surfaceView sera votre vue "caméra". En plus, vous pouvez ajouter toutes vos mises en page. – Entreco

Questions connexes