
使用 `viewcompat.setonapplywindowinsetslistener` 监听软键盘高度时,若直接返回原始 `insets` 会导致状态栏颜色丢失;正确做法是调用 `viewcompat.onapplywindowinsets(v, insets)` 透传并兼容处理系统窗口插图,从而保留状态栏、导航栏等系统 ui 的正常渲染。
在 Android 开发中,通过 ViewCompat.setOnApplyWindowInsetsListener 监听软键盘(IME)弹出/收起是获取动态键盘高度的常用方式。但许多开发者发现:一旦设置该监听器并简单返回 insets,原本通过 window.setStatusBarColor() 或主题 android:statusBarColor 设置的状态栏会突然变为白色(或透明),甚至 Activity 内容还会意外上移、覆盖状态栏或导航栏——这本质上是因未正确处理 WindowInsets 分发导致系统默认行为被中断。
根本原因在于:onApplyWindowInsetsListener 是一个拦截式回调。若你返回原始 insets(如 return insets;),系统无法确认该 insets 是否已被“消费”或“透传”,进而跳过对 DecorView 及其子视图(包括状态栏背景渲染逻辑)的标准 insets 处理流程,最终破坏了 StatusBarColor 的布局预留与绘制上下文。
✅ 正确解法:不自行消费,而是委托给 ViewCompat.onApplyWindowInsets()
该静态方法会执行完整的兼容性处理链:自动分发 insets 给子视图、尊重 fitsSystemWindows 属性、保留系统 UI(状态栏/导航栏)的 padding 和背景渲染逻辑,并返回处理后的 insets —— 既满足你的监听需求,又不干扰系统 UI 行为。
以下是修正后的完整代码示例:
ViewCompat.setOnApplyWindowInsetsListener(
this.getWindow().getDecorView(),
(v, insets) -> {
// ✅ 安全获取键盘高度(仅 IME 类型)
int keyboardHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
Log.d("KeyboardHeight", String.valueOf(keyboardHeight));
SharedPreferences prefs = getSharedPreferences("MyPreferences", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
if (keyboardHeight > 0) {
// 键盘弹出:隐藏底部区域
bottom.getLayoutParams().height = 0;
editor.putInt("keyboard_height", keyboardHeight);
} else {
// 键盘收起:恢复底部区域高度
bottom.getLayoutParams().height = prefs.getInt("keyboard_height", 500);
}
editor.apply();
bottom.requestLayout(); // ? 别忘了刷新布局
// ✅ 关键修复:交由 ViewCompat 全面处理 insets,保留状态栏/导航栏渲染
return ViewCompat.onApplyWindowInsets(v, insets);
}
);⚠️ 注意事项:
- 切勿返回 WindowInsetsCompat.CONSUMED:虽然文档提到它可终止分发,但 CONSUMED 会彻底阻止系统对状态栏背景、padding 等的默认处理,导致颜色丢失和布局错位;
- 确保 bottom 视图已初始化且非 null,并在修改 LayoutParams 后调用 requestLayout();
- 若使用 CoordinatorLayout 或 NestedScrollView,建议将监听器注册在具体目标子视图(如 findViewById(R.id.root_layout))而非 DecorView,避免全局干扰;
- 在 Activity 的 onCreate() 中设置监听器前,请确认 window.setFlags(FLAG_LAYOUT_NO_LIMITS, ...) 等全屏标志未被误设——它们会主动抑制状态栏渲染。
总结:WindowInsets 是 Android 系统协调系统 UI 与应用内容的关键机制。与其手动“接管” insets,不如信任 ViewCompat.onApplyWindowInsets() 的兼容层实现——它已针对各 Android 版本做了充分适配,是你安全监听键盘高度同时守住状态栏颜色的最优实践。










