1. WindowManager 初探:什么是 WindowManager?它的核心职责是什么?为什么 Android 需要它?

大家好,我是你们的老朋友。今天咱们来聊聊 Android 世界里一个既熟悉又神秘的角色——WindowManager

说实话,我刚开始做 Android 开发那会儿,对 WindowManager 的理解就停留在「能弹个悬浮窗」的层面。直到有一次,我接手了一个直播项目的画中画功能,才真正被它「上了一课」。嗯,从那以后,我再也不敢小看这个家伙了。

什么是 WindowManager?

简单来说,WindowManager 是 Android 系统中管理窗口的接口。它负责决定每个窗口的位置、大小、层级和显示方式。

你想想看,你的手机屏幕上同时跑着那么多 App——状态栏、通知栏、输入法、悬浮球、Toast 提示……它们是怎么做到井水不犯河水的?

答案就是:WindowManager 在背后统一调度

它不是一个「视图」,也不是一个「布局」。它是一个系统服务,一个协调者。每个窗口想要出现在屏幕上,都得先跟 WindowManager 打个招呼。

核心定义:WindowManager 是一个接口,继承自 ViewManager。它提供了添加、更新、删除窗口的能力。每个窗口对应一个 View,而 WindowManager 负责把这个 View 挂载到屏幕上。

它的核心职责是什么?

我习惯把 WindowManager 的职责拆成三块来讲。这样比较好记,也方便理解。

1. 窗口的添加、更新与移除

这是最基础的能力。任何一个窗口,从生到死,都离不开这三个操作。

  • addView:把 View 注册到 WindowManager 中,让它出现在屏幕上。
  • updateViewLayout:窗口的位置、大小、层级变了,通知 WindowManager 刷新。
  • removeView:窗口不再需要了,从屏幕上移除。

我记得有一次,我在做悬浮球功能时,忘了调用 updateViewLayout,结果拖拽后位置死活不更新。排查了半天,才发现是 LayoutParams 改了但没通知 WindowManager。嗯,这个坑我踩过,你们别踩了。

2. 窗口层级的统一管理

Android 的窗口是有「优先级」的。状态栏永远在最上面,输入法紧随其后,普通 App 窗口在下面。

这个优先级,就是通过 WindowManager.LayoutParams 中的 type 字段来控制的。

窗口类型 type 值 典型用途
应用窗口 FIRST_APPLICATION_WINDOW ~ LAST_APPLICATION_WINDOW Activity 的主窗口
子窗口 FIRST_SUB_WINDOW ~ LAST_SUB_WINDOW Dialog、PopupWindow
系统窗口 FIRST_SYSTEM_WINDOW ~ LAST_SYSTEM_WINDOW 状态栏、Toast、输入法

说白了,type 值越小,层级越靠下。系统窗口的 type 值很大,所以它们能盖住普通 App。

注意:从 Android 6.0 开始,系统窗口权限(SYSTEM_ALERT_WINDOW)需要用户手动授权。我曾经在适配某款国产手机时,发现悬浮窗权限默认是关闭的,结果功能直接崩溃。所以,记得在代码里做好权限检查。

3. 窗口的布局与测量

WindowManager 还负责把 WindowManager.LayoutParams 中的布局参数(宽、高、x、y、gravity 等)转换成实际的窗口位置。

它不直接参与 View 的测量和绘制,但它决定了 View 的「容器」有多大、在哪儿。

举个例子:

WindowManager.LayoutParams params = new WindowManager.LayoutParams(
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.WRAP_CONTENT,
    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    PixelFormat.TRANSLUCENT
);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 100;
params.y = 200;

windowManager.addView(myView, params);

这段代码的意思是:创建一个悬浮窗,不获取焦点,位置在屏幕左上角偏移 (100, 200) 像素处。嗯,就是这么直接。

为什么 Android 需要 WindowManager?

这个问题,我当年也问过自己。为什么不能直接用 Activity 或 Dialog 搞定所有事情?

原因其实很简单:Android 是一个多窗口系统

你想想看,一个手机屏幕上,可能同时存在:

  • 一个 Activity 的主窗口
  • 一个悬浮的 Dialog
  • 一个 Toast 提示
  • 一个输入法面板
  • 一个系统状态栏

这些窗口来自不同的进程、不同的应用。如果没有一个统一的「窗口管理员」,它们就会乱成一锅粥。

WindowManager 就是那个「管理员」。它负责:

  • 协调层级:谁在上面,谁在下面,不能乱。
  • 统一输入事件分发:触摸事件该发给哪个窗口,由 WindowManager 决定。
  • 管理窗口动画:窗口的打开、关闭、切换动画,也由它调度。
  • 提供系统级窗口能力:比如 Toast、输入法、壁纸,这些都不是普通 App 能直接控制的。

个人经验:我建议你在做悬浮窗、画中画、全局弹窗这类功能时,先想清楚「这个窗口的生命周期归谁管」。如果它跟 Activity 绑定,用 Dialog 就够了。如果它需要独立于 Activity 存在,那就必须走 WindowManager。

知识体系总览

下面这张图,是我自己梳理的 WindowManager 核心知识结构。你可以把它当作整个课程的地图。

WindowManager 窗口生命周期管理 窗口层级调度 布局与测量 addView / updateViewLayout / removeView type 字段控制优先级 LayoutParams 参数解析 ⚠️ 权限检查:SYSTEM_ALERT_WINDOW ⚠️ 窗口类型与安全限制 ⚠️ 悬浮窗适配问题 核心:统一管理所有窗口的显示与交互

小结

好了,咱们来捋一捋今天的内容。

WindowManager 不是什么高深莫测的东西。它就是一个「窗口大管家」。你给它一个 View,它帮你放到屏幕上;你告诉它窗口的层级,它帮你排好顺序;你调整窗口的位置,它帮你重新布局。

说白了,没有 WindowManager,Android 的多窗口体系就转不起来

我个人觉得,理解 WindowManager 的关键,不在于背 API,而在于理解它的「调度逻辑」。你想想看,一个系统里同时跑着几十个窗口,谁先谁后、谁大谁小、谁能触摸谁不能触摸——这些规则,才是 WindowManager 真正的灵魂。

下一节,我会带大家深入 WindowManager.LayoutParams,看看那些参数到底是怎么控制窗口行为的。嗯,到时候见。


公众号:蓝海资料掘金营,微信deep3321