2011-04-25 267 views
7

和其他許多人一樣,我試圖在相機預覽(使用SurfaceView)上繪製3D對象(使用GLSurfaceView)以及放置在頂部的一些按鈕。我實際上有一個原型工作,但我無法正確地使onResume正常工作。簡歷後,GLSurfaceView留在後面,不再可見。我知道它正在工作,因爲如果從佈局中移除SurfaceView,我可以很好地看到圖紙。如何在Android上正確使用setZOrderMediaOverlay?

目標是Nexus One,運行庫存2.3.3 ROM。

這裏的佈局XML:

<com.example.cameratest.GLPreview 
     android:id="@+id/cubes" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent"/> 

<com.example.cameratest.Preview 
     android:id="@+id/camera" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent"/> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/buttongroup" 
    android:orientation="vertical" 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:layout_gravity="right" android:gravity="center"> 

    <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonClose"></Button> 
    <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonMode"></Button>  
    <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/buttonCameraInfo"></Button> 
</LinearLayout> 

所有這一切都被包裹在一個<merge>塊,但由於某些原因,我無法包括在上述<code>上市。 Preview是擴展SurfaceView並實現相機預覽邏輯的類。

這項工作正常,當活動啓動。在我啓動另一個活動(例如,通過按下其中一個按鈕)並完成該活動後,主要活動恢復,但3D對象不再可見。

我發現this discussion其中提到setZOrderMediaOverlay()將有助於解決這種z排序問題。此外,Android document for setZOrderMediaOverlay()說這個函數應該被稱爲「在表面視圖的包含窗口被附加到窗口管理器之前」。我不知道該如何解釋該語句,因此我在代碼中放置了調試語句以查看事件序列。下面是GLSurfaceView代碼的樣子:


public class GLPreview extends GLSurfaceView 
{ 
    private static final String TAG = "GLPreview"; 

    public GLPreview(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     // this.setZOrderMediaOverlay(true);   
    } 

    public void onPause() 
    { 
     super.onPause(); 
     Log.d(TAG, "GLPreview: OnPause"); 
    } 

    public void onResume() 
    { 
     // this.setZOrderMediaOverlay(true);   
     super.onResume(); 
     Log.d(TAG, "GLPreview: OnResume"); 
    } 

    public void surfaceCreated(SurfaceHolder holder) 
    { 
     Log.d(TAG, "GLPreview: surfaceCreated"); 
     super.surfaceCreated(holder); 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
    { 
     Log.d(TAG, String.format("GLPreview: surfaceChanged, format=%d, w=%d, h=%d", format, w, h)); 
     super.surfaceChanged(holder, format, w, h); 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     Log.d(TAG, "GLPreview: surfaceDestroyed"); 
     super.surfaceDestroyed(holder); 
    } 

    protected void onAttachedToWindow() 
    { 
     Log.d(TAG, "GLPreview: onAttachedToWindow"); 
     super.onAttachedToWindow(); 
    } 

    protected void onDetachedFromWindow() 
    { 
     Log.d(TAG, "GLPreview: onDetachedFromWindow"); 
     super.onDetachedFromWindow(); 
    } 

    protected void onWindowVisibilityChanged (int vis) 
    { 
     String newVisibility; 
     switch (vis) 
     { 
      case View.GONE: 
       newVisibility = "GONE"; 
       break; 
      case View.INVISIBLE: 
       newVisibility = "INVISIBLE"; 
       break; 
      case View.VISIBLE: 
       newVisibility = "VISIBLE"; 
       break; 
      default: 
       newVisibility = String.format("Unknown constant %d", vis); 
     } 

     Log.d(TAG, String.format("GLPreview: onWindowVisibilityChanged -> %s", newVisibility)); 
     super.onWindowVisibilityChanged(vis); 
    } 
} 
 

這裏是當我啓動應用程序的事件序列:

 
GLPreview: OnResume 
GLPreview: onAttachedToWindow 
GLPreview: onWindowVisibilityChanged -> VISIBLE 
GLPreview: surfaceCreated 
GLPreview: surfaceChanged, format=1, w=800, h=480 

所以我認爲setZOrderMediaOverlay()需要在任何onResume()或在構造函數中調用。但是,我嘗試了setZOrderMediaOverlay()truefalseGLSurfaceViewSurfaceView類的各種組合,但它們都沒有幫助解決問題。

我在Android編程方面比較新。我到目前爲止,但在這一點上,我需要一些幫助。如果某人在此場景中成功使用setZOrderMediaOverlay(),並且與onResume()合作,請告訴我如何完成此操作。

非常感謝!

+1

FWIW,看到http://stackoverflow.com/questions/5648221/fighting-with-surfaceview-camera-and-opengl/25020225#25020225約重疊SurfaceViews一些注意事項。 – fadden 2014-07-29 16:24:55

回答

14

我已經在同一個問題上掙扎了一段時間,但相信下面的代碼現在可以工作。 (無論相機開啓還是關閉,在暫停/鎖定後它都會繼續工作)。

首先,我沒有在佈局文件中定義任何視圖等 - 它們是在代碼中創建的。從主onCreate()方法調用以下內容 - 請注意augScreen上的setZOrderMediaOverlay()。

除了將onPause()和onResume()傳遞給augScreen外,我沒有在onPause()或onResume()中做任何特殊的事情。

 // 1 - Camera Preview 
     camScreen = new CameraPreview(this); 
     setContentView(camScreen, new LayoutParams(
       LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 

    // 2 - 3D object display 
     augScreen = new AR_SurfaceView(this, getViewRange()); 
     addContentView(augScreen, new LayoutParams(
       LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 
     augScreen.setZOrderMediaOverlay(true); 

    // 3 - Permanent overlay 
    RelativeLayout overlayScreen = new OverlayView(this); 
    addContentView(overlayScreen, new LayoutParams(
      LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
    overlayScreen.setVisibility(View.VISIBLE); 

    // 4 - UI buttons (toggleable) 
     uiScreen = new UserInterfaceView(this); 
     addContentView(uiScreen, new LayoutParams(
       LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
+1

謝謝,在'onCreate()'中調用'setZOrderMediaOverlay()'解決了這個問題。順便說一句,我仍然有XML佈局文件;我沒有將應用程序轉換爲在代碼中構建視圖。 我知道我沒有提到這個問題,但同一個應用程序有一些代碼,用於在相機預覽表面上繪製(顯示fps的簡單DrawText)。現在我必須弄清楚爲什麼在我實現'setZOrderMediaOverlay()'改變後代碼停止工作。 – alokoko 2011-05-23 16:51:21

+0

通過「不工作」,我的意思是代碼被調用,我看到相機預覽和3D對象,但fps文本不再被繪製在相機預覽表面上。 Hmmmmmm。 – alokoko 2011-05-23 17:05:22

0

Awila_Tech的回答也幫助了我。我使用了一個GLSurfaceView,並且在Activity的onPause和onResume中整齊地調用onPause和onResume,但是在調用實際的onDrawFrame時,我的屏幕中只有1次保持黑屏。

總結:

public class OpenGLApp extends Activity implements GLSurfaceView.Renderer { 
    private GLSurfaceView mGLSurfaceView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     mGLSurfaceView = new GLSurfaceView(this); 
     mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8); 
     mGLSurfaceView.setRenderer(this); 
     mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 
     mGLSurfaceView.setKeepScreenOn(true); 
     mGLSurfaceView.setDrawingCacheEnabled(true); 
     mGLSurfaceView.setZOrderOnTop(true); 

     setContentView(mGLSurfaceView); 
     //... 
    } 

    @Override 
    protected void onPause() { 
     //... 
     mGLSurfaceView.onPause(); 
     super.onPause(); 
    } 

    @Override 
    protected void onResume() { 
     mGLSurfaceView.onResume(); 
     //... 
     super.onResume(); 
    } 
} 
+0

皮特,你不應該在mGLSurfaceView之前調用super.onPause()和super.onResume()嗎? – 2012-12-21 22:40:53

相關問題