Window表示是一个窗口的概念,它是一个抽象类,具体的实现是PhoneWindow,创建一个Window是很简单的事,只需要通过WindowManager就可以完成,Android中所有的视图都是通过Window来实现的,比如Activity,Toast和Dialog,当我们需要做悬浮窗口的需求的时候,就需要用到它们,下面来看看
Window和WindowManager
先来看看如何通过WindowManager添加一个Window
Button button=new Button(this);
WindowManager wmManager=(WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams lp=new WindowManager.LayoutParams();
lp.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
lp.gravity= Gravity.TOP;
lp.x=100;
lp.y=300;
wmManager.addView(button,lp);
代码很简单,创建一个view之后就可以用WindowManager的addView方法引用到屏幕x=100和y=300坐标上了,其实WindowManager常用的方法就是添加view,更新view和删除view,也就是addView,updateViewLayout和removeView
(一)Flags
参数表示Window的属性,它有很多选项,通过这些选项可以控制Window的显示特性
FLAG_NOT_FOCUSABLE
表示window不需要获取焦点,这个比较好理解,设置了这个属性后,window将不会获取到焦点
FLAG_NOT_TOUCH_MODAL
在此模式下,系统会将当前Window区域以外的单击事件传递给底层的Window,当前Window区域以内的单击事件则自己处理。 一般来说都需要开启此标记,否则其他Window将无法收到单击事件
FLAG_SHOW_WHEN_LOCKED
此模式可以让Window显示在锁屏的界面上
(二)Type
Type代表的是window的类型,共有3种,分别是:应用window,子window和系统window,应用window对应一个Activity,子window需要依附在父window上,不能单独存在,比如dialog,系统window就是系统提供的,比如toast,状态栏等,这些在使用的时候需要声明权限,否则报错,每一类型的window都有一个范围
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
应用window(1-99):Activity,Fragment等
子window(1000-1999):Dialog,Popupwindow等
系统window(2000-2999):Toast,状态栏,通知等
层级范围对应这WindowManager.LayoutParams的type参数,层级大的会覆盖在层级小的Window上面。所以系统层级是最大的,系统层级一般选用TYPE_SYSTEM_ERROR或者TYPE_SYSTEM_OVERLAY
上面提到了windowManger对view的操作有addView,updateViewLayout和removeView,这3个方法定义在ViewManager中,而WindowManger是继承了ViewManager,我们来看看这三个方法:
public interface ViewManager
{
/**
* Assign the passed LayoutParams to the passed View and add the view to the window.
* <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming
* errors, such as adding a second view to a window without removing the first view.
* <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a
* secondary {@link Display} and the specified display can't be found
* (see {@link android.app.Presentation}).
* @param view The view to be added to this window.
* @param params The LayoutParams to assign to view.
*/
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
这3个功能足够我们平常用了,其实WindowManager操作Window的过程就好像Window操作view的过程,我们有时候看到那些可以拖动Window的效果,其实就可以通过updateViewLayout来实现,设置view的onTouchListener,然后根据手指拖动来改变x和y的值,不断更新view就可以了
button.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getRawX();
int y= (int) event.getRawY();
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
lp.x=x;
lp.y=y;
wmManager.updateViewLayout(button,lp);
break;
}
return false;
}
});
好了,这篇文章到这就结束了