(1)获取WindowManager类的实例----WindowManager类作为系统服务之一,也可以用getSystemService来获取:
private static WindowManager getWindowManager(Context context) {
if (mWindowManager == null) {
mWindowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
}
return mWindowManager;
}
(2)WindowManager类的常用方法。应用中最常用到的方法有3中:addView、removeView、updateViewLayout
void android.view.ViewManager.addView(View view, LayoutParams params)添加View视图
void android.view.ViewManager.removeView(View view)移除View视图
void android.view.ViewManager.updateViewLayout(View view, LayoutParams params)更新View视图的参数
简单看下这3个函数可以观察到里面的参数只有两种View和LayoutParams,主要这里的LayoutParams是WindowManager.LayoutParams而不是其他ViewGroup的参数;这里的View可以是系统的也可以是我们自定义的View;而WindowManager.LayoutParams就比较复杂了,下面记录下具体含义。
(3)WindowManager.LayoutParams
1) 我们主要是通过WindowManager向界面添加一个窗口,那么所谓窗口都有一个窗口类型,在Android中窗口类型的取值有多种,我们常用的一般都是在应用窗口之上,但是在状态栏之下,即:TYPE_PHONE;下面定义type的取值:
应用程序窗口。
public static final int FIRST_APPLICATION_WINDOW = 1;
所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。
public static final int TYPE_BASE_APPLICATION =1;
普通应哟功能程序窗口。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;
子窗口。子窗口的Z序和坐标空间都依赖于他们的宿主窗口。
public static final int FIRST_SUB_WINDOW = 1000;
面板窗口,显示于宿主窗口上层。
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
媒体窗口,例如视频。显示于宿主窗口下层。
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1;
应用程序窗口的子面板。显示于所有面板窗口的上层。(GUI的一般规律,越“子”越靠上)
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW +2;
对话框。类似于面板窗口,绘制类似于顶层窗口,而不是宿主的子窗口。
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW +3;
媒体信息。显示在媒体层和程序窗口之间,需要实现透明(半透明)效果。(例如显示字幕)
public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW +4;
子窗口结束。( End of types of sub-windows )
public static final int LAST_SUB_WINDOW = 1999;
系统窗口。非应用程序创建。
public static final int FIRST_SYSTEM_WINDOW = 2000;
状态栏。只能有一个状态栏;它位于屏幕顶端,其他窗口都位于它下方。
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;
搜索栏。只能有一个搜索栏;它位于屏幕上方。
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;
电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;
系统提示。它总是出现在应用程序窗口之上。
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW +3;
锁屏窗口。
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW +4;
信息窗口。用于显示toast。
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW +5;
系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。
public static final int TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW +6;
电话优先,当锁屏时显示。此窗口不能获得输入焦点,否则影响锁屏。
public static final int TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW +7;
系统对话框。(例如音量调节框)。
public static final int TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW +8;
锁屏时显示的对话框。
public static final int TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW +9;
系统内部错误提示,显示于所有内容之上。
public static final int TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW +10;
内部输入法窗口,显示于普通UI之上。应用程序可重新布局以免被此窗口覆盖。
public static final int TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW +11;
内部输入法对话框,显示于当前输入法窗口之上。
public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW +12;
墙纸窗口。
public static final int TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW +13;
状态栏的滑动面板。
public static final int TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW +14;
系统窗口结束。
public static final int LAST_SYSTEM_WINDOW = 2999;
2)flag窗口的flag标志,下面主要列举常用的flag
FLAG_NOT_FOCUSABLE不能获得焦点
FLAG_NOT_TOUCHABLE不接受触摸屏事件
FLAG_NOT_TOUCH_MODAL
3)期望的位图格式format
format的值默认为不透明的。他的取值主要是通过PixelFormat类。
4)gravity,以我自己的理解,这个字段的含义就是设置坐标的起始点,例如常用的有Gravity.LEFT | Gravity.TOP,就是以左上角作为开始。设置了坐标起始点后就可以设置他的x、y坐标了,同时设置View的长和宽了。这里设置x、y坐标的时候需要注意状态栏的高度问题。也就是通过:
int height = mWindowManager.getDefaultDisplay().getHeight();
int width = mWindowManager.getDefaultDisplay().getWidth();
得到显示屏的长宽后,设置x、y坐标注意减去状态栏的高度,至于状态栏的高度计算方法可以参考之前的记录。
在对LayoutParams各个字段的参数进行设置后就可以调用以上方案进行窗口的操作了。
最后记得添加权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />