理解Window和WindowManager(一)

Window和WindowManager

Window是一个抽象类,具体实现是PhoneWindow。Window的具体实现位于WindowManagerService中。所有的视图都是通过Window来呈现的,Window实际是View的直接管理者。

创建Window通过WindowManager(每个窗口管理器实例都绑定一个特定的Display(即Activity、Dialog))完成,WindowManager是外界访问Window的入口,WindowManager和WindowManagerService的交互是一个IPC过程。

使用WindowManager添加一个Window

        mFloatingButton = new Button(this);
        mFloatingButton.setText("button");
        mLayoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT);
        mLayoutParams.gravity = Gravity.CENTER;
        mLayoutParams.x = 100;
        mLayoutParams.y = 300;
        mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        // 8.0以上需要这样设置type
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mLayoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            mLayoutParams.type = LayoutParams.TYPE_SYSTEM_ALERT;
        }
        mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        if (mWindowManager != null) {
            mWindowManager.addView(mFloatingButton, mLayoutParams);
        }

声明权限

因为 LayoutParams.TYPE_APPLICATION_OVERLAY和LayoutParams.TYPE_SYSTEM_ALERT是系统类型的Window,所以要在AndroidManifest中使用相应的权限

 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

此外,还需在代码里手动申请获得手机的相关权限:

if (Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivityForResult(intent, 1);
} else {
    addWindow();
}

WindowManager.LayoutParams中的参数

Flags参数

表示Window的属性,可以控制Window的显示特性

1.FLAG_NOT_FOCUSABLE

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

2.FLAG_NOT_TOUCH_MODAL

系统会将当前Window区域以外的单击事件传递给底层的Window,当前Window区域以内的单击事件则自己处理。一般来说都会开启此标记,否则其他Window将无法收到单击事件。

3.FLAG_SHOW_WHEN_LOCKED

可以让Window显示在锁屏的界面上,只适用于最顶层的全屏幕Window。(这个参数在AIP27时过期了,推荐使用 R.attr.showWhenLocked参数或者Activity.setShowWhenLocked(boolean))

Type参数

表示Window的类型

Window的类型

Window是分层的,每个Window都有对应的z-ordered,层级大的会覆盖在层级小的Window上面,层级范围对应着type参数

1.应用Window

对应着一个Activity,层级范围1~99

2.子Window

不能单独存在,需要附属在特定的父Window之中,比如Dialo。层级范围1000~1999

3.系统Window

需要声明权限才能创建,比如Toast和系统状态栏。层级范围2000~2999

// 应用Window的层级范围
public static final int FIRST_APPLICATION_WINDOW = 1;
public static final int LAST_APPLICATION_WINDOW = 99;
// 子Window的层级范围
public static final int FIRST_SUB_WINDOW = 1000;
public static final int LAST_SUB_WINDOW = 1999;
// 系统Window的层级范围
public static final int FIRST_SYSTEM_WINDOW = 2000;
public static final int LAST_SYSTEM_WINDOW = 2999;

WindowManager提供的方法

常用的只有以下三个方法,这三个方法定义在ViewManager中,WindowManager继承了ViewManager
WindowManager操作Window的过程更像是在操作Window中的View

public interface ViewManager {
    void addView(View var1, LayoutParams var2);

    void updateViewLayout(View var1, LayoutParams var2);

    void removeView(View var1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值