2011-08-19 19 views
7

Mam prosty ekran z przyciskiem start. Po naciśnięciu przycisku Start, chcę przejść do nowego ekranu z SurfaceView, aby pokazać kamerę.Pokaż mój układ podczas ładowania SurfaceView Podgląd kamery

Wszystko działa dobrze, ale aparat potrzebuje trochę czasu, aby załadować, a to daje mi czarny ekran. Chciałbym załadować nowy układ. I uruchomić aparat niż po to został załadowany ...

Nich, robię wszystko ładowanie kamery w wątku tła, ale nadal, mam czarny ekran ... Oto mój plan:

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

Oto metoda z mojej działalności, który ładuje nowy widok:

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

Jak to się stało, nowy układ nie jest widoczny, dopóki wątek zakończeniu ładowania aparatu?

EDIT: Próbowałem Thread.Sleep (200) w obrębie wątku spać przez jakiś czas ... Kiedy robię, że nowy układ jest pokazany immedeately, ale kamera nie uruchamia ...

Odpowiedz

20

W porządku, problem polega na tym, że użyłem mojego SurfaceView w układzie xml. Gdy zadzwonisz: setContentView (your_layout) -> plik XML jest zawyżony. Oznacza to, że SurfaceView jest również napompowany. To znowu oznacza, że ​​wywoływana jest metoda SurfaceView onSurfaceCreated, która uruchamia otwieranie kamery, itp.

Cały proces trwa trochę dłużej, dlatego Twoja poprzednia czynność (np. Uruchomienie działania z SurfaceView) wydaje się nie odpowiadać ...

Moje rozwiązanie, polegające na utworzeniu CameraView w wątku BG, rozwiązuje problem braku reakcji. Ale nie udało się pokazać wyjścia kamery w SurfaceView.

Rozwiązaniem jest usunięcie SurfaceView z twojego xml. Spowoduje to natychmiastowe rozpoczęcie działania (ponieważ kamera SurfaceView & nie jest tworzona). Po załadowaniu nowego układu Aktywności można programowo dodać nowy ekran SurfaceView do ekranu. Oczywiście, wymaga to czasu, ale twój interfejs użytkownika szybko przełącza się na nową czynność i możesz pokazać program ładujący podczas ładowania SurfaceView i aparatu!

SO: usunąć SURFACEVIEW OD XML -> dodaj ją programowo: uruchamianie Aktywny:

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 (tylko przycisk, aby rozpocząć nową działalność)

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

Oto druga czynność (która zawiera 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); 
    } 
} 

A tu jest t Drugi układ Activity on (bez A 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> 

Na koniec, aby zakończyć odpowiedź, oto kod dla CameraView().To naprawdę jest tylko prosta implementacja, aby otworzyć aparatem i wyświetlać zawartość:

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

Przewodnik Android Developers również polecam zadzwonić Camera.open() w WorkerThread aby uniknąć blokowania UI wątek. –

+1

Ten kod działa idealnie dobrze ... co, jeśli chcę dodać do niego mój układ? –

+1

W xml utwórz relatywny obiekt z widokiem powierzchni. Ten surfaceView będzie twoim widokiem "kamery". Oprócz tego możesz dodać wszystkie swoje układy. – Entreco

Powiązane problemy