将用"窗口管理局"的比喻,结合源码解析这篇文章的核心内容。窗口属性就像店铺的经营许可证,决定了窗口如何显示、如何交互以及如何与其他窗口共存。
🏢 第一章:窗口属性登记表(LayoutParams)
在Android系统中,每个窗口在创建时都需要填写一份"属性登记表",这就是WindowManager.LayoutParams
类。它包含三大核心属性:
scala
java
Copy
public static class LayoutParams extends ViewGroup.LayoutParams {
public int type; // 窗口类型(决定层级)
public int flags; // 窗口标志(行为控制)
public int softInputMode; // 软键盘交互模式
}
📋 第二章:窗口类型(Type)------ 决定店铺等级
窗口类型决定了窗口的层级关系(Z-Order),就像商业街的店铺位置:高档商铺在显眼位置,小摊位在角落。类型分为三大类:
1. 应用程序窗口(1~99)
arduino
java
Copy
public static final int TYPE_APPLICATION = 2; // 普通App窗口
public static final int TYPE_APPLICATION_STARTING = 3; // App启动时的临时窗口
- 比喻:正规商铺(如Activity)
- 特点:需要用户交互,位于中间层级
2. 子窗口(1000~1999)
arduino
java
Copy
public static final int TYPE_APPLICATION_PANEL = 1000; // 面板型子窗口
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 对话框
- 比喻:商铺内的展示柜(必须依附于主店铺)
- 关键特性 :必须指定父窗口(
token
属性) - 典型代表:Dialog
3. 系统窗口(2000~2999)
arduino
java
Copy
public static final int TYPE_STATUS_BAR = 2000; // 状态栏
public static final int TYPE_TOAST = 2005; // Toast
public static final int TYPE_PHONE = 2002; // 电话窗口(来电显示)
- 比喻:公共设施(如路灯、公交站)
- 权限要求 :需要声明
SYSTEM_ALERT_WINDOW
权限 - 特殊规则:Toast(TYPE_TOAST)在Android 7.1后无需权限
🎚️ 层级规则(Z-Order)
-
基本规则:Type值越大,窗口层级越高(越靠近用户)
-
示例:
cssA[Activity<br>TYPE=2] --> B[Dialog<br>TYPE=1003] B --> C[Toast<br>TYPE=2005]
实际显示顺序:Toast > Dialog > Activity
🚩 第三章:窗口标志(Flags)------ 经营行为规范
Flags控制窗口的交互行为,就像商铺的经营规则(是否允许夜间营业、是否接受刷卡等)。常用Flags如下:
Flag值 | 作用描述 |
---|---|
FLAG_NOT_FOCUSABLE |
窗口不获取焦点(无法接收输入事件) |
FLAG_NOT_TOUCHABLE |
窗口不响应触摸事件(事件会穿透) |
FLAG_KEEP_SCREEN_ON |
窗口可见时保持屏幕常亮 |
FLAG_FULLSCREEN |
全屏显示(隐藏状态栏) |
FLAG_SHOW_WHEN_LOCKED |
在锁屏界面之上显示(用于闹钟提醒) |
FLAG_LAYOUT_NO_LIMITS |
允许窗口超出屏幕边界 |
⚙️ 设置Flags的三种方式
-
动态添加(推荐):
scssjava Copy // 示例:设置全屏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-
覆盖设置:
scssjava Copy // 清空旧Flags并设置新值 getWindow().setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN);
-
通过LayoutParams设置(适用于系统窗口):
inijava Copy LayoutParams params = new LayoutParams(); params.flags = FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE; windowManager.addView(view, params);
⌨️ 第四章:软键盘模式(SoftInputMode)------ 避免键盘遮挡
控制软键盘弹出时窗口的调整行为,就像商铺如何应对临时检查(是调整货架还是原地等待)。
常用模式:
模式值 | 行为描述 |
---|---|
SOFT_INPUT_ADJUST_RESIZE |
窗口调整大小(内容自动上移) |
SOFT_INPUT_ADJUST_PAN |
窗口平移(保持输入框可见) |
SOFT_INPUT_STATE_HIDDEN |
进入窗口时默认隐藏键盘 |
SOFT_INPUT_STATE_ALWAYS_VISIBLE |
进入窗口时总是显示键盘 |
⚙️ 设置方式:
-
在AndroidManifest中声明:
inixml Copy <activity android:windowSoftInputMode="adjustResize|stateHidden" />
-
代码动态设置:
scssjava Copy getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
💡 第五章:实战示例解析
案例1:全屏游戏窗口
scss
java
Copy
// 设置全屏 + 保持常亮 + 隐藏导航栏
getWindow().addFlags(
FLAG_FULLSCREEN |
FLAG_KEEP_SCREEN_ON |
FLAG_LAYOUT_NO_LIMITS
);
案例2:锁屏显示闹钟
scss
java
Copy
// 锁屏显示 + 触摸穿透 + 点亮屏幕
getWindow().addFlags(
FLAG_SHOW_WHEN_LOCKED |
FLAG_NOT_TOUCHABLE |
FLAG_TURN_SCREEN_ON
);
案例3:聊天界面避免键盘遮挡
scss
java
Copy
// 键盘弹出时调整布局 + 默认隐藏键盘
getWindow().setSoftInputMode(
SOFT_INPUT_ADJUST_RESIZE |
SOFT_INPUT_STATE_HIDDEN
);
📊 属性优先级与冲突处理
当多个属性冲突时,WMS按以下优先级处理:
- Type值:决定基础层级(系统窗口 > 子窗口 > 应用窗口)
- Flags :修改交互行为(如
FLAG_NOT_FOCUSABLE
会覆盖默认焦点行为) - 软键盘模式:仅当键盘弹出时生效
⚠️ 注意:系统窗口需要权限!
Android 6.0+ 使用
TYPE_TOAST
无需权限,其他系统窗口需:
inixml Copy <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
总结:窗口属性三大件
- Type:决定窗口层级(你是谁?)
- Flags:控制交互行为(你能做什么?)
- SoftInputMode:键盘交互策略(如何应对输入?)
理解这些属性,就能精准控制窗口的显示逻辑,避免"键盘遮挡输入框"、"全屏时状态栏残留"等常见问题。下一讲我们将深入Window的添加过程!