原文链接:Android开发之WindowManager的使用详解、android之surfaceView详解--自定义surfaceView和用于视频surfaceview
最近需要做个应用,显示layer分为三层,由下往上是:Activity,SurfaceView,View。
而SurfaceView又是一个View中的控件。
而现在需求是:将SurfaceView的父布局全屏,而SurfaceView部分显示。
之前没有接触过显示视频相关的概念,参考上文链接博客。也记录一下WindowManager的使用。
使用Surface须知:
创建了一个SurfaceView之后,可以调用其成员函数getHolder()获得一个SurfaceHodler对象,然后再调用该SurfaceHolder对象的成员函数setType来修改该SurfaceView的绘图表面的类型,即修改该SurfaceView的成员变量mRequestedType的值。
1)如果mRequestedType = SURFACE_TYPE_NORMAL,则表示该SurfaceView的绘图表面锁使用的内存是一块普通的内存。一般来说,这块内存是由SurfaceFlinger服务来分配的,可以在应用程序内部自由地访问它,即可以在它上面填充任意的UI数据,然后交给SurfaceFlinger服务来合成,并且显示在屏幕上。这种情况下,SurfaceFlinger服务使用一个Layer对象来描述该SurfaceView的绘图表面。
2)如果mRequestedType = SURFACE_TYPE_PUSH_BUFFERS的时候,就表示该SurfaceView的绘图表面所使用的内存不是由SurfaceFlinger服务分配的,因为我们不能在应用程序内部对它进行操作。例如,当一个SurfaceView是用来显示摄像头预览或者视频播放的时候,我们就会将它的绘图表面的类型设置为SURFACE_TYPE_PUSH_BUFFERS,这样摄像头服务或者视频播放服务就会为该SurfaceView绘图表面创建一块内存,并且将采集的预览图像数据或者视频帧数据源源不断地填充到该内存中去。注意,这块内存有可能是来自专用的硬件的,例如,它可能来自视频卡的。在这种情况下,SurfaceFlinger服务使用一个LayerBuffer对象来描述该SurfaceView的绘图表面。
从上面的描述中得到一个很重要的结论:绘图表面类型为SURFACE_TYPE_PUSH_BUFFERS的SurfaceView的UI是不能由应用程序来控制的,而是由专门的服务来控制的。例如,摄像头服务或者视频播放服务,同时SurfaceFlinger服务会使用一种特殊的LayerBuffer来描述这种绘图表面。使用LayerBuffer来描述的绘图表面在进行渲染的时候,可以使用硬件加速,例如,使用copybit或者overlay来加快渲染速度,从而可以获得更流畅的摄像头预览或者视频播放。
WindowManager是Android中一个重要的Service,是全局且唯一的。WindowManager继承自ViewManager。
WindowManager主要用来管理窗口的一些状态、属性、view增加、删除、更新、窗口顺序、消息收集和处理等。Android中真正展示给用户的是window和view,activity所起的作用主要是处理一些逻辑问题,比如生命周期管理及建立窗口。
在WindowManager中还有一个重要的静态类LayoutParams.通过它可以设置和获得当前窗口的一些属性。
一、实现悬浮窗口
1、获取WindowManager服务:
WindowManager wmManager=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
2、设置WindowManager.LayoutParams参数
WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
wmParams.type = LayoutParams.TYPE_PHONE; // 设置window type
wmParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE;
wmParams.gravity = Gravity.RIGHT| Gravity. CENTER_VERTICAL; // 调整悬浮窗口至右侧中间
wmParams.x = 0;// 以屏幕左上角为原点,设置x、y初始值
wmParams.y = 0;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;// 设置悬浮窗口长宽数据
wmParams.height =WindowManager.LayoutParams.WRAP_CONTENT;
3、添加View到屏幕
wmManager.addView(view,wmParams);
4、从屏幕上删除View
wmManager.removeView(view);
5、悬浮窗口需在AndroidManifest.xml中添加权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
二、获取屏幕宽高
wmManager.getDefaultDisplay().getWidth();
wmManager.getDefaultDisplay().getHeight();
三、改变Dialog的透明度
Dialog dg = new Dialog(this);
Window window = dg.getWindow();
WindowManager.LayoutParams lp = window.getAttributes();
lp.alpha = 0.5f;
window.setAttributes(lp);