You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Activity重建或切换夜间模式时Edge-to-edge功能失效问题

切换主题后Edge-to-Edge失效,Insets监听不触发的解决方案

调用AppCompatDelegate.setDefaultNightMode切换日间/夜间主题后,Activity重建恢复状态,但Edge-to-edge功能失效,setOnApplyWindowInsetsListener未被触发。该问题在模拟器及部分三星设备上复现,Pixel 9设备正常。


相关代码

BaseActivity.kt 启用Edge-to-edge

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d(Const.TAG_ACTIVITY, String.format("%s BaseActivity onCreate()", this.javaClass.simpleName))
    enableEdgeToEdge()
    initBinding()
    onActivityCreate(savedInstanceState)
    observeLiveData()
}

InsetsManager.kt 设置Insets监听

object InsetsManager {

fun applyBottomNavigationViewInsets(bottomContainerView: ViewGroup) {
    ViewCompat.setOnApplyWindowInsetsListener(bottomContainerView) { v, windowInsets ->
        val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
        v.setPadding(insets.left, insets.top, insets.right, insets.bottom)

        WindowInsetsCompat.CONSUMED
    }
}

fun applyTutorialInsets(view: MainPageTutorialView, promotionsTutorial: PromotionsPageTutorialView) {
    ViewCompat.setOnApplyWindowInsetsListener(view) { _, windowInsets ->
        val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())

        view.insetsTop = insets.top.toFloat()
        view.insetsLeft = insets.left.toFloat()
        view.insetsRight = insets.right.toFloat()
        view.insetsBottom = insets.bottom.toFloat()
        promotionsTutorial.insetsTop = insets.top.toFloat()
        promotionsTutorial.insetsBottom = insets.bottom.toFloat()

        WindowInsetsCompat.CONSUMED
    }
}
}

已排查/尝试的操作

  • ✅ enableEdgeToEdge()在setContentView()之前调用
  • ✅ setOnApplyWindowInsetsListener在onCreate()中setContentView()之后调用
  • ❌ 在onStart、onResume中调用enableEdgeToEdge()无效
  • ❌ 配置configChanges="uiMode"并在onConfigurationChanged()中调用enableEdgeToEdge()及手动recreate()无效
  • ❌ 移除AndroidManifest.xml中的launchMode="singleTop"无效

解决方案

方案1:手动锁定DecorView的Edge-to-Edge配置

主题切换重建后,系统可能意外重置DecorView的fitsSystemWindows属性,导致Edge-to-edge失效。在enableEdgeToEdge()后强制设置该属性为false:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d(Const.TAG_ACTIVITY, String.format("%s BaseActivity onCreate()", this.javaClass.simpleName))
    enableEdgeToEdge()
    // 强制关闭fitsSystemWindows,确保Edge-to-edge生效
    window.decorView.fitsSystemWindows = false
    initBinding()
    onActivityCreate(savedInstanceState)
    observeLiveData()
}

方案2:主动触发Insets重新计算

Activity重建后,系统可能不会自动派发Insets事件,手动请求目标视图重新计算Insets,强制触发监听回调:

// 在你的Activity实现的onActivityCreate方法末尾添加
override fun onActivityCreate(savedInstanceState: Bundle?) {
    // 原有设置Insets监听的代码
    InsetsManager.applyBottomNavigationViewInsets(binding.bottomContainer)
    InsetsManager.applyTutorialInsets(binding.tutorialView, binding.promotionsTutorial)
    
    // 强制触发Insets重新计算
    ViewCompat.requestApplyInsets(binding.bottomContainer)
    ViewCompat.requestApplyInsets(binding.tutorialView)
}

方案3:调整Insets消费逻辑

如果布局中存在多层视图需要处理Insets,不要直接返回WindowInsetsCompat.CONSUMED,改为返回原Insets,避免阻断Insets传递:

fun applyBottomNavigationViewInsets(bottomContainerView: ViewGroup) {
    ViewCompat.setOnApplyWindowInsetsListener(bottomContainerView) { v, windowInsets ->
        val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
        v.setPadding(insets.left, insets.top, insets.right, insets.bottom)

        // 返回原Insets,允许其他视图继续处理
        windowInsets
    }
}

方案4:使用WindowInsetsController替代(可选)

通过WindowInsetsController直接控制系统栏,兼容性更稳定:

// 在BaseActivity中配置
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()
    window.decorView.fitsSystemWindows = false
    
    // 初始化InsetsController,控制系统栏行为
    val insetsController = WindowCompat.getInsetsController(window, window.decorView)
    insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    
    initBinding()
    onActivityCreate(savedInstanceState)
    observeLiveData()
}

内容的提问来源于stack exchange,提问作者Nazar Taraniuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:28:13