第八章(1) 理解Window和WindowManager

理解Window和WindowManager

Window表示一个窗口的概念,Window是一个抽象类,它的具体实现是PhoneWindow。创建一个Window是一个很简单的事,只需要通过WindowManager即可完成。WindowManager是外界访问Window的入口。

Android中所有的视图都是通过Window来呈现的,不管是ActivityDialog还是Toast,它们的视图实际上都是附加在Window上的,因此Window实际是View的直接管理者。

Button mFloatingButton = new Button(this);
mFloatingButton.setText("button");
WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT
        ,0,0,
        PixelFormat.TRANSPARENT
);
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;

mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 300;

mWindowManager.addView(mFloatingButton, mLayoutParams);

上述代码可以将一个Button添加到屏幕坐标为(100,300)的位置上。WindowManager.LayoutParams中的flagstype这两个参数比较重要。

Flags参数表示Window的属性,它有很多选项,通过这些选项可以控制Window的显示特性,这里主要介绍几个比较常用的选项。

  • FLAG_NOT_FOCUSABLE

表示Window不需要获取焦点,也不需要接收各种输入事件,此标记会同时启用FLAG_NOT_TOUCH_MODAL,最终事件会直接传递给下层的具有焦点的Window

  • FLAG_NOT_TOUCH_MODAL

在此模式下,系统会将当前Window区域以外的单击事件传递给底层的Window,当前Window区域以内的单击事件则自己处理。这个标记很重要,一般来说,都需要开启此标记。

  • FLAG_SHOW_WHEN_LOCKED

开启此模式可以让Window显示在锁屏的界面上。

Type参数表示Window的类型,Window有三种类型,分别是应用Window子Window系统Window应用类Window对应着一个Activity子Window不能单独存在,它需要附属在特定的父Window之中,比如常见的一些Dialog就是子Window。系统Window是需要声明权限在能创建的Window,比如Toast和系统状态栏这些都是系统Window

Window是分层的,每个Window都有对应的z-ordered,层级大的会覆盖在层级小的Window的上面。在三类Window中,应用Window的层级范围是1~99,子Window的层级范围是1000~1999,系统Window的层级范围是2000~2999,这些层级范围对应着WindowManager.LayoutParamstype参数。很显然系统Window的层级是最大的,而且系统层级有很多值,一般我们可以选用TYPE_SYSTEM_OVERLAY或者TYPE_SYSTEM_ERROR,如果采用TYPE_SYSTEM_ERROR,只需要为type参数指定这个层级即可:mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,同时声明权限。因为系统类型的Window是需要检查权限的,如果不在AndroidManifest中使用相应的权限,那么创建Window的时候就会报错。

WindowManager所提供的功能很简单,常用的只有三个方法,即添加View更新View删除View,这三个方法定义在ViewManager中,而WindowManager继承了ViewManager

public interface ViewManager
{
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

对开发者来说,WindowManager常用的就只有这三个功能而已,但是这三个功能已经足够我们使用了。它可以创建一个Window并向其添加View,还可以更新Window中的View,另外如果想要删除一个Window,那么只需要删除它里面的View即可。由此来看,WindowManager操作Window的过程更像是在操作Window中的View。我们时常见到那种可以拖动的Window效果,其实是很好实现的,只需要根据手指的位置来设定LayoutParams中的xy的值即可改变Window的位置。首先给View设置onTouchListener:btn.setOnTouchListener(this)。然后在onTouch方法中不断更新View的位置即可。

btn.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                layout.x = rawX;
                layout.y = rawY;
                manager.updateViewLayout(btn,layout);
                break;
        }

        return false;
    }
});

你可能感兴趣的:(第八章(1) 理解Window和WindowManager)