参考链接:
http://www.cnblogs.com/mengdd/p/3824782.html
1.理清概念
我们使用过Dialog和PopupWindow,还有Toast,它们都显示在Activity之上。那么我们首先需要理解的是android中是如何去绘制这些UI的呢?这里我只讲我所理解的,首先看一层次图(盗用网络)
首先我们看到左边的Activity层,我们使用到的Activity,其中会有一个PhoneWindow,这个每一个Activity都包含的,并且PhoneActivity去管理一个DecoView根视图,并且这也解释了我们使用的
s
etContentView(int resId)就是将所有的UI组件放入到PhoneWindow中管理。我们也看到DecoView,加载后的资源都放入到这个View中。接下来会看到WindowManager,
整个Android的窗口机制是基于一个叫做WindowManager,
这个接口可以添加view到屏幕,也可以从屏幕删除view。它面向的对象一端是屏幕,另一端就是View。而我们的android屏幕可以放多个窗口,除了Activity,我们还可以放Dialog,PopupWindow,我研究了一下PopupWIndow,就是通过WindowManager生产的。如果要自定义一个窗口,我们可以不用Dialog和PopupWindow,可以自己来实现它。
理解该图,首先思考的是使用的Activity,会有一个PhoneWindow,这个用来管理View。而它的视图是如何被绘制出来的呢,那是WindowManager的事情了,WindowManager就是添加和移除View,从屏幕上。
2.WindowManager介绍
WindowManager的方法很简单,有三个方法,AddView(),removeView(),updateViewLayout();
AddView();
//添加View
removeView();
//移除VIew
updateViewLayout()
//更新View
接下来看一个完整的代码:
View view = LayoutInflater.from(this).inflate(R.layout.dialog,null); //加载View视图,这个就是我们要显示的内容
WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); //获取WindowManage
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
//设置LayoutParams的属性
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; //该Type描述的是形成的窗口的层级关系,下面会详细列出它的属性
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | //该flags描述的是窗口的模式,是否可以触摸,可以聚焦等
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
layoutParams.gravity = Gravity.CENTER; //设置窗口的位置
layoutParams.format = PixelFormat.TRANSLUCENT; //不设置这个弹出框的透明遮罩显示为黑色
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; //窗口的宽
layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; //窗口的高
layoutParams.token = ((View)findViewById(R.id.linearlayout)).getWindowToken(); //获取当前Activity中的View中的TOken,来依附Activity,因为设置了该值,纳闷写的这些代码不能出现在onCreate();否则会报错。
windowManager.addView(view,layoutParams); //显示窗口
别忘了在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
(1)那么接下啦介绍type值
layoutParams.type
窗口类型。其中有三种主要类型:
Applicationwindows:
取值在 FIRST_APPLICATION_WINDOW 和 LAST_APPLICATION_WINDOW 之间。
是通常的、顶层的应用程序窗口。必须将 token 设置成 activity 的 token 。
Sub_windows:
取值在 FIRST_SUB_WINDOW 和 LAST_SUB_WINDOW 之间。
与顶层窗口相关联,token 必须设置为它所附着的宿主窗口的 token。
Systemwindows:
取值在 FIRST_SYSTEM_WINDOW 和 LAST_SYSTEM_WINDOW 之间。
用于特定的系统功能。它不能用于应用程序,使用时需要特殊权限。
取值在 FIRST_APPLICATION_WINDOW 和 LAST_APPLICATION_WINDOW 之间。
是通常的、顶层的应用程序窗口。必须将 token 设置成 activity 的 token 。
Sub_windows:
取值在 FIRST_SUB_WINDOW 和 LAST_SUB_WINDOW 之间。
与顶层窗口相关联,token 必须设置为它所附着的宿主窗口的 token。
Systemwindows:
取值在 FIRST_SYSTEM_WINDOW 和 LAST_SYSTEM_WINDOW 之间。
用于特定的系统功能。它不能用于应用程序,使用时需要特殊权限。
应用程序窗口。
public static final int FIRST_APPLICATION_WINDOW = 1;
所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。
public static final int TYPE_BASE_APPLICATION =1;
public static final int FIRST_APPLICATION_WINDOW = 1;
所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。
public static final int TYPE_BASE_APPLICATION =1;
//-----------------------------------------------
Applicationwindows ------------//
普通应用功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。
public static final int TYPE_APPLICATION = 2;
用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。
它用于让系统显示些信息,直到应用程序可以开启自己的窗口。
public static final int TYPE_APPLICATION_STARTING = 3;
应用程序窗口结束。
public static final int LAST_APPLICATION_WINDOW = 99;
普通应用功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。
public static final int TYPE_APPLICATION = 2;
用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。
它用于让系统显示些信息,直到应用程序可以开启自己的窗口。
public static final int TYPE_APPLICATION_STARTING = 3;
应用程序窗口结束。
public static final int LAST_APPLICATION_WINDOW = 99;
//-----------------------------------------------
Applicationwindows ------------//
//-----------------------------------------------
Sub_windows
------------//
子窗口。子窗口的Z序和坐标空间都依赖于他们的宿主窗口。
public static final int FIRST_SUB_WINDOW = 1000;
public static final int FIRST_SUB_WINDOW = 1000;