Android 兩個surfaceview疊加的問題
最近在做安卓視訊通話,用到webrtc,要求跟對方通話的時候右上角小視窗展示本地視訊,底層展示遠端視訊,想到的方法是在Framelayout裡面巢狀兩個org.webrtc.SurfaceViewRenderer(繼承自SurfaceView),把遠端SurfaceView放在下面,把本地SurfaceView放在上面,如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parent_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <org.webrtc.SurfaceViewRenderer android:id="@+id/remoteVideoView" android:layout_width="match_parent" android:layout_height="match_parent" /> <org.webrtc.SurfaceViewRenderer android:id="@+id/localVideoView" android:layout_width="150dp" android:layout_height="200dp" android:layout_gravity="top|right" android:fitsSystemWindows="true" /> </FrameLayout>
但是結果是在華為mate9上(Android O)顯示正常,在海信手機(Android L)上顯示異常,查看了相關的文件 SurfaceView
The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes.
surface是縱深排序(Z-ordered)的,這表明它總在自己所在視窗的後面。surfaceview提供了一個可見區域,只有在這個可見區域內 的surface部分內容才可見,可見區域外的部分不可見。surface的排版顯示受到檢視層級關係的影響,它的兄弟檢視結點會在頂端顯示。這意味者 surface的內容會被它的兄弟檢視遮擋,這一特性可以用來放置遮蓋物(overlays)(例如,文字和按鈕等控制元件)。注意,如果surface上面 有透明控制元件,那麼它的每次變化都會引起框架重新計算它和頂層控制元件的透明效果,這會影響效能。
兩個SurfaceView建立的先後順序不受Framelayout影響,是由重新計算的Surface的建立順序決定的,並且,SurfaceView提供了介面來對其Z-ordered進行排序。
public void setZOrderOnTop (boolean onTop)
Added in API level 5
Control whether the surface view's surface is placed on top of its window. Normally it is placed behind the window, to allow it to (for the most part) appear to composite with the views in the hierarchy. By setting this, you cause it to be placed above the window. This means that none of the contents of the window this SurfaceView is in will be visible on top of its surface.
Note that this must be set before the surface view's containing window is attached to the window manager.
Calling this overrides any previous call to
setZOrderMediaOverlay(boolean)
.
因此,我們可以講本地surfaceview設定為setZOrderOnTop (true),那麼就可以達到將本地SurfaceView展示在遠端SurfaceView上層的目的了。