androidwindowinsetsandroid-15edge-to-edge

Edge-to-edge doesn't work when activity recreated or AppCompatDelegate.setDefaultNightMode() applied


I have this code for enabling edge-to-edge in my BaseActivity.kt class

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()
}

And this code for enabling insets listeners for applying correct padding to the views

override fun onActivityCreate(savedInstanceState: Bundle?) {
    InsetsManager.applyBottomNavigationViewInsets(bind.bottomNavContainer)
    InsetsManager.applyTutorialInsets(bind.tutorial, bind.promotionsTutorial)
}

Here is the code of InsetsManager.kt

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
    }
}

}

Everything is working fine, until I call AppCompatDelegate.setDefaultNightMode(//no matter which mode) to change the theme for example from Day to Night. Then as expected Activity is being recreated and restored all its state including fragments, but the edge-to-edge does not apply again and the setOnApplyInsetsListeners haven't called

What I've already checked:

  1. enableEdgeToEdge() is being called before setContentView()
  2. setOnApplyWindowInsetsListener called inside onCreate() after setContentView()

What I've already tried:

  1. Called enableEdgeToEdge() in onStart, onResume (didn't work)
  2. Enabled configChanges="uiMode" and called enableEdgeToEdge() inside onConfigurationChanged() and manually called recreate() (didn't work)
  3. I had a launchMode="singleTop" in my AndroidManifest.xml, tried to remove it (didn't work)

This bug reproduced by me on an emulator, and some Samsung devices. On my personal Pixel 9 everything works fine as expected.

Here is some examples.

Dark mode enabled (AppCompatDelegate.MODE_NIGHT_YES)

enter image description here

Light mode enabled (AppCompatDelegate.MODE_NIGHT_NO)

(Don't pay attention to isAppearanceLightStatusBar thing, I will fix that later)

enter image description here


Solution

  • As Mike M. mentioned, there was a bug during activity recreation and his suggested workaround is the solution. So, for those who also faced this issue, you should do:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Add these 3 lines to your code
        if (savedInstanceState != null && Build.VERSION.SDK_INT >= 35) {
            WindowCompat.setDecorFitsSystemWindows(window, false)
        }
        enableEdgeToEdge()
    }