Adjust UI when system bars are showing Android

786 Views Asked by At

I am using this code to hide the status bar and navigation bar from the app:

val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())

But is there any way to prevent the navigation and status bar from showing above my app content?

Am I able to detect when the status bar is going to appear to set a padding/margin on the top view to prevent it from hiding my views?

If I could at least get the statusBar or navigationBar visibility could I prevent this behavior by applying an animation on the views (to go up or down and leave the space for status/navigation bar?

2

There are 2 best solutions below

0
Zain On BEST ANSWER

But is there any way to prevent the navigation and status bar from showing above my app content?

If the user intentionally drag the top or the bottom of the screen to show the system bars; then no way to to prevent the navigation and status bars from showing above the app's content. Why? Because this drag is a part of system UI, not your app's window; check this answer for more in detail.

But, if the developer intentionally show these bars, then yes margins can be added to these bars to prevent overlapping with the app's content.

To get the height of these bars; register WindowInsetsListener to the root ViewGroup of your app, and get that from the insets.

Here is a demo:

var bottomNavigationHeight = 0
var statusBarHeight = 0

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)
    val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
    windowInsetsController.systemBarsBehavior =
        WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
    windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())


    // root ViewGroup of the activity
    val root = findViewById<ConstraintLayout>(R.id.root)
    val onApplyWindowInsetsListener =
        OnApplyWindowInsetsListener { _: View?, windowInsets: WindowInsetsCompat ->
            val insets =
                windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
            bottomNavigationHeight = insets.bottom
            statusBarHeight = insets.top

            WindowInsetsCompat.CONSUMED
        }
    ViewCompat.setOnApplyWindowInsetsListener(root, onApplyWindowInsetsListener)

    // some button to show up the system bars
    findViewById<Button>(...).setOnClickListener {

        // apply the margin to the system bars
        (root.layoutParams as FrameLayout.LayoutParams).apply {
            topMargin = statusBarHeight
            bottomMargin = bottomNavigationHeight
        }

        // show the system bars
        windowInsetsController.show(WindowInsetsCompat.Type.systemBars())

    }
}
0
Daniel Knauf On

You can listen to changes to the WindowInsets and adjust your view accordingly.

ViewCompat.setOnApplyWindowInsetsListener(VIEW){ view, insets ->
    val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())

    val insetsTop = systemBarInsets.top
    val insetsBottom = systemBarInsets.bottom

    // adjust your view with padding and/or margin

    insets // return insets or WindowInsetsCompat.CONSUMED to prevent forwarding insets to other views

}