androidandroid-fragmentsandroid-bottomnavigationviewwindowinsets

Reverting Window Insets on fragment change


I have three fragments. I want to apply a transparent status bar on just one fragment. For that purpose, I am calling the following hide method on the setOnItemSelectedListener method of the bottom navigation bar. Also added an image of what I am getting right now

private fun hideStatusBar() {
    window.statusBarColor = ContextCompat.getColor(this@SuperActivity, R.color.transparent)
    WindowCompat.setDecorFitsSystemWindows(window, false)
    ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
      val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())

      view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
        leftMargin = insets.left
        rightMargin = insets.right
        bottomMargin = insets.bottom
      }
      WindowInsetsCompat.CONSUMED
    }
  }
    

  private fun showStatusBar() {
    window.statusBarColor = ContextCompat.getColor(this@SuperActivity, R.color.transparent)
    WindowCompat.setDecorFitsSystemWindows(window, true)
  }

I am getting the appropriate behavior on fragment calling hide method. enter image description here

But when I tap on another fragment (the one that needs to show the status bar), I get the following behaviour:

enter image description here


Solution

  • The bottom margin by default is 0 (or the designated value in the root layout "binding.root")

    So, you need to reset the bottom margin again; if it's already 0; then you can:

    private fun showStatusBar() {
        window.statusBarColor = ContextCompat.getColor(this@SuperActivity, R.color.transparent)
        WindowCompat.setDecorFitsSystemWindows(window, true)
    
        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
          val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
    
          view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            bottomMargin = 0 // reset the margin
          }
          WindowInsetsCompat.CONSUMED
        }
      }
    }
    

    Or if it's something else; then you need to convert that from dp to pixels and set it to the bottomMargin

    The same thing applies if you have some designated margin values in binding.root; but I think you didn't as the issue only appears at the bottom.

    UPDATE:

    The method setOnApplyWindowInsetsListener is not called inside showStatusBar method. Because in this, the Window Insets are not changed. Since, we added margin in hideStatusBar method, so this space that you see below navigation bar is from hideStatusBar method.

    Although the listener should be triggered, but you can update the root directly:

    binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
        bottomMargin = 0
    }
    

    But notice that the setDecorFitsSystemWindows can take some time to update, so updateLayoutParams wouldn't have the effect, so, you might need a little delay for that:

    Handler(Looper.getMainLooper()).postDelayed( {
        binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            bottomMargin = 0
        }
     }, 0.1.toLong())