Android两个SurfaceView叠加显示

原创 2016年09月21日 23:17:44

最近一段时间一直在做智能后视镜产品(Android平台)里的相机模块,目前已经告一段落了。现在空闲的时候可以把一些技术点记录下来。

其中有一个需求就是显示前、后两个摄像头的预览画面,并且可以相互切换显示。

类似下面这个样子:
这里写图片描述

在Android里常用来显示相机预览的就是SurfaceView,因为不需要在UI线程刷新。那这里我们考虑的就是将两个SurfaceView叠加在一起显示。

布局xml(部分):

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"  android:layout_gravity="center_vertical|center_horizontal" >      
        < SurfaceView
            android:id="@+id/usb_preview_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <SurfaceView
            android:id="@+id/mipi_preview_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>

这样子就可以把两个SurfaceView以全屏的形式叠加在一起了。
那问题是怎样去切换这两个界面呢?

像普通的view一样设置其可见性setVisibility,将上层的SurfaceView设置不可见就可以显示下层的SurfaceView了。
但是实际是不可行的,SurfaceView和普通的View不一样,它拥有一个独立于Activity之外的Window,当SurfaceView被设置为不可见的时候,其所对应的Window就会销毁,再想去显示这个SurfaceView的时候就不得不重新创建;另外,SurfaceView创建的先后顺序也是不受FrameLayout的规则影响的,一般来说,布局xml文件中FrameLayout布局靠后的view会覆盖考前的view,但SurfaceView是根据其对应的Surface创建的先后顺序决定的。

那另一种思路就是,两个SurfaceView叠在一起后,将上层的SurfaceView所在Window设置成透明的,如果需要显示下面SurfaceView的内容,就将上层SurfaceView的绘制区域缩小到1、2像素的范围,肉眼看不见,显示的就是下层SurfaceView的内容了;显示上层SurfaceView的时候,就全屏绘制了。这里SurfaceView对应Window的大小是不会动态改变的,改变的只是图像绘制区域的大小。

设置透明的方法,是通过SurfaceHolder来设置的,注意调用的位置,否则无效。
mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);

API文档里的:
public abstract void setFormat (int format)
****Added in API level 1
Set the desired PixelFormat of the surface. The default is OPAQUE. When working with a SurfaceView, this must be called from the same thread running the SurfaceView’s window.**

这种方式实际是可行的,但是也有局限性。Android框架上,我们只需初始化SurfaceHolder,再通过Camera中setPreviewDisplay(holder)后启动预览,就可以自动display the surface了。也就是说,如果想改变SurfaceView绘制的区域,就得重新设置大小和位置,并重新启动相机预览,比较耗时,而且在后台录像的情况下是不可行的。

还好我们这里在上层的SurfaceView是用来显示USB摄像头的预览,就是在Canvas上将图像一帧帧绘制出来的。

Canvas canvas = getHolder().lockCanvas();
if (canvas != null) {
    if (mCurrentPreviewState == USB_PREVIEW) {
        rect.set(IMG_WIDTH / 2, IMG_HEIGHT / 2, IMG_WIDTH, IMG_HEIGHT);
        canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
        canvas.drawBitmap(mPreviewBitmap, null, rect, null);
    } else {
        canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
        canvas.drawBitmap(mPreviewBitmap, null, rect, null);
    }                   
    getHolder().unlockCanvasAndPost(canvas);
}

两个surfaceview的重叠效果类似直播效果中的视频和讲义实践

效果图首先还是不废话,直接上一张图,有图才有真相,不然大家看半天才发现不是我想要的效果,所以这样浪费大家的时间了实际应用场景可多了,比如后面是显示相机的数据,前面是一个画板,直播的视频和讲义展示布局布...
  • renpingqing
  • renpingqing
  • 2016年06月04日 19:05
  • 4200

Android视图SurfaceView的实现原理分析

在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独...
  • Luoshengyang
  • Luoshengyang
  • 2013年03月16日 16:57
  • 201017

Android两个Surface重叠显示

项目需求,相机预览做背景surfaceView1,播放其VideoView在其上,即:1个surfaceview获取相机预览数据作为背景(CustomCameraView),1个surfaceview...
  • iblade
  • iblade
  • 2016年10月11日 20:10
  • 2144

两个surfaceView切换的demo

需求:视频通话界面,两个surfaceView一个显示本端的视图,另一个显示对端的视图,由于显示比例的问题总会存在一个覆盖另一个的问题,为保证用户体验,规定小的覆盖大的视图上面,且点击小的视图可切花为...
  • xuedaqian123
  • xuedaqian123
  • 2017年09月07日 11:16
  • 412

多个SurfaceView层叠显示问题

当场景中有多个SurfaceView的时候,上层的SurfaceView可能会被下层的遮挡,这个时候需要使用setZOrderOnTop(true)或者setZOrderMediaOverlay(tr...
  • lakeinchina
  • lakeinchina
  • 2013年10月17日 10:37
  • 12542

两个surfaceview重叠显示

最近在做人脸识别的项目,需要在做一个动画效果来追踪人脸的位置,遇到了这个问题。 1个surfaceview获取相机预览数据作为背景, 1个surfaceview在前一surfa...
  • u013071408
  • u013071408
  • 2017年09月22日 20:11
  • 526

【android 使用两个surfaceview 在摄像机画面上绘图】

使用双surface,将第一个设置为透明背景,在摄像机上绘制图像,纠结搞了一天。 其中参考了http://blog.csdn.net/yanzi1225627/article/details/793...
  • Jesse__Zhong
  • Jesse__Zhong
  • 2014年05月03日 21:03
  • 9644

surfaceview叠加问题(地图上显示视频)

终于忙里抽闲可以总结一下最近忙的晕头转向的东西了 公司的app是以地图为主(即主界面是地图 其他界面都是覆盖上层的fragment),产品出了新的设计,是要在地图上弹出一个界面覆盖在地图上层,里面...
  • mingyue_1128
  • mingyue_1128
  • 2015年07月22日 15:39
  • 1946

解决SurfaceView设置透明造成覆盖其他组件的替代方案

之前在项目里面绘制摇杆圆盘使用SurfaceView来实现,同时设置SurfaceView透明,但是这样会造成SurfaceView的组件会覆盖其他的组件,一般情况没有关系,而不一般的情况就是有类似上...
  • jwzhangjie
  • jwzhangjie
  • 2013年07月25日 20:08
  • 18923

Android双SurfaceView实现底部拍照,顶部绘图

当SurfaceHolder对象的类型设置为SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS时就只能拍照不能绘制了。 为了既能通过SurfaceView拍照又能在上面绘...
  • xinzheng_wang
  • xinzheng_wang
  • 2012年07月04日 10:36
  • 16654
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android两个SurfaceView叠加显示
举报原因:
原因补充:

(最多只允许输入30个字)