2011-04-13 56 views
11

我們一直在爭取一些與SurfaceViews有關的問題超過一週,並且找不到適當的解決方案。我們閱讀論壇中有關類似問題(甚至Mixare源代碼)的其他問題,但無法找到答案,所以我們希望您能以某種方式幫助我們。與SurfaceView,相機和OpenGL戰鬥

情景: 我們有

  • 一個SurfaceView您的相機
  • 了一個OpenGL層,肚裏相機頂部的SurfaceView。
  • 另一個視圖,它顯示了一些關於我們可以在屏幕上看到的信息。這個是在兩個SurfaceView之上的。

問題:

無論我們怎麼努力,都SurfaceViews顯然不彼此相處得很好。如果我們嘗試:

setContentView(mCameraPreview); 
addContentView(mGLSurfaceView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 
addContentView(mInfoView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 

(這似乎是合乎邏輯的),一切都按預期進行,直到我們鎖定/解鎖手機。之後,GLSurfaceView就消失了(不是InfoView,它仍然顯示)。

相反,如果我們嘗試:

setContentView(mGLSurfaceView); 
addContentView(mCameraPreview, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 
addContentView(mInfoView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 

那麼問題是,GLSurfaceView只鎖定/解鎖後出現,並且屏幕顯示相機和InfoView中之前。

我們發現,如果我們在顯示視圖的活動中執行onStart()之後的4.6秒(或更多)睡眠主線程,則行爲與預期相同(顯示相機,glsurface和信息視圖,甚至鎖定/解鎖後)。

問題是,我們正在尋找更多......優雅的解決方案。

在我們看來,這個問題是相機拍攝的Camera.open()比預期更多的時間,所以添加了攝像頭查看,添加了GLSurfaceView,當相機實際打開,它會打開在GLSurfaceView的頂部。對此,我們在GLSurfaceView上使用了bringToFront(),並將其置於信息視圖之上,但在鎖定/解鎖之後,相機依然在其上打開,只留下一個僅帶相機預覽的屏幕。

任何想法?我們如何在其上顯示SurfaceViews和信息視圖?

+0

你的問題遠遠超出我的理解 - 但要確保你正在調用GLSurfaceView.onPause()和GLSurfaceView.onResume(),正如你應該從容器Activity中調用一樣。這就是我能想到的這個話題。 – harism 2011-04-13 12:49:34

+0

看來我們正試圖解決同樣的問題。我沒有看到你的問題,當我發佈[我自己的](http://stackoverflow.com/questions/5778647/how-to-properly-use-setzordermediaoverlay-on-android)。你嘗試過'setZOrderMediaOverlay()'嗎?我嘗試過,但無法實現這種情況。也許你可以弄清楚如何使用它並解決這個問題。 – alokoko 2011-04-26 16:37:57

回答

2

我有同樣的問題。當你暗示自己:多個SurfaceView不相處,因爲他們的Z順序是不確定的。

在我的Samsung Galaxy S2上,訂購與您描述的相同(不知道它是如何在其他手機上)。 我解決這個問題的方法,是檢查第一次創建ActivityonCreate()的:

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

    //... 

    if (savedInstanceState == null) 
    { 
     initCamView(); 
     initOpenGL(); 
    } 
    else 
    { 
     initOpenGL(); 
     initCamView(); 
    } 

    //... 
} 

有:

private void initOpenGL() 
{ 
    mGLSurfaceView = new GLSurfaceView(this); 
    mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); 
    mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); 

    mOGLRenderer = new OGLRenderer(this); 
    mGLSurfaceView.setRenderer(mOGLRenderer); 
    mRL.addView(mGLSurfaceView); // mRL is the Relative Layout 
} 

和:

private void initCamView() 
{ 
    mCamView = new CustomCameraView(this.getApplicationContext(), 
            this.getWindowManager()); 
    mRL.addView(mCamView); // mRL is the Relative Layout 
} 

不是最優雅的解決方案,但它比讓線程睡眠4.6秒更好。

也可以將屏幕鎖定在單一方向,但是您需要做很多醜陋的黑客操作才能使覆蓋圖以正確的方式旋轉。或者,如果您只定位到Android 3.0或更高版本(API級別8),則只需在OpenGL SurfaceTexture中顯示相機即可。 http://developer.android.com/reference/android/hardware/Camera.html#setPreviewTexture(android.graphics.SurfaceTexture

4

試試這個:

mLayout.addView(mRenderView); 
mLayout.addView(mCustomSurfaceView); 

// without this line, the camera preview cannot be displayed 
// when running activity at first time. 
mCustomSurfaceView.setZOrderMediaOverlay(true); 

這個工作對我來說:)

+0

完美,這導致我設置ZOrderOnTop(onTop),這正是我正在尋找 – 2016-02-26 00:30:08

1

我有同樣的問題:我想下一個GLSurfaceView SurfaceView,播放視頻的第一和第二運行一個遊戲。

無論我做了什麼,這兩個表面視圖之間的z順序似乎是隨機的。

但我找到了解決辦法,這要歸功於這個帖子:https://stackoverflow.com/a/6028907/1557915

關鍵是去除使用的佈局,而是使用的setContentView/addContentView。

1

每個SurfaceView的表面都有Z-depth。有三種可能的深度:默認(底部),「媒體覆蓋」(在它上面)和「頂部」(這是最重要的,包括基於視圖的UI)。如果您在同一深度有兩個重疊的曲面,其中一個會贏,但您無法可靠地定義哪一個。您可能會在一臺設備上獲得一致的行爲,但發現它在另一臺設備上以另一種方式工作。

在可能的情況下,使用硬件覆蓋層完成構圖。許多當前流行的設備有4個覆蓋平面。一旦你超過了這一點,這個組合就會用GPU來完成,而這將會更加昂貴。如果你有一個狀態欄,導航欄和View UI,那麼你只需要一個SurfaceView便宜。

對於問題中的示例,最好將盡可能多的東西組合到用GLES呈現的表面上。這可以包括API 11+上的攝像頭輸出。舉例來說,請參閱Grafika中的「來自相機的紋理」活動。 (Grafika也有一個包含三個重疊SurfaceView的演示應用程序;請參閱「多表面測試」活動)。

如果您想了解更多關於爲什麼SurfaceView的行爲方式如此,請參閱Android System-Level Graphics文檔。