为什么WindowCompat.setDecorFitsSystemWindows在API>=30的Dialog窗口失效
问题根因
- 调用时机不对:
onViewCreated执行时,Dialog的窗口属性还未完成最终初始化,DialogFragment内部会在onViewCreated执行结束后、Dialog 正式显示前,重写 Window 的decorFitsSystemWindows相关配置,API 30+ 上这个内部覆写逻辑优先级更高,会直接覆盖你在onViewCreated中的修改。 - 系统机制变更:Android 11(API 30)对弹窗类窗口的 WindowInsets 处理逻辑做了调整,默认会自动接管
fitsSystemWindows行为,如果不在 Dialog 创建的最早阶段声明自定义配置,后续的修改都会被系统默认逻辑覆盖。
修复方案
将 Window 配置逻辑迁移到 onCreateDialog 方法中执行,这是 Dialog 配置窗口属性的最早有效时机,修改后的代码如下:
class SuperDuperDialog: DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val dialog = super.onCreateDialog(savedInstanceState) // 提前在Dialog创建时配置Window属性 dialog.window?.let { WindowCompat.setDecorFitsSystemWindows(it, false) } return dialog } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) ViewCompat.setOnApplyWindowInsetsListener(binding.root) { root, insets -> doSomethingWithDialogMargins() insets } } }
注意事项
- 检查 Dialog 对应的自定义主题,不要在 style 中配置
android:fitsSystemWindows="true",否则会覆盖代码中的配置。 - 如果 Dialog 有自定义背景,避免给背景设置额外的边距占用系统 inset 区域,导致边距计算异常。
内容的提问来源于stack exchange,提问作者Denis Dda
相关产品推荐
相关产品推荐

