androidandroid-jetpack-compose

Draw behind hidden status bar in Jetpack Compose


To make sure the problem is not in my own code, I have created a new, empty project with a very basic MainActivity.kt:

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

        // enable full screen:
        // https://developer.android.com/jetpack/compose/layouts/insets#insets-setup
        enableEdgeToEdge()

        // enable immersive mode:
        // https://developer.android.com/develop/ui/views/layout/immersive
//        WindowInsetsControllerCompat(window, window.peekDecorView()).apply {
//            hide(WindowInsetsCompat.Type.statusBars())
//            systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
//        }

        setContent {
            Box(modifier = Modifier
                .fillMaxSize()
                .background(Color.Red)) {
                Text("Hello")
            }
        }
    }
}

When WindowInsetsControllerCompat is commented out (like in the example above), the result is as expected - the content is drawn behind the status and navigation bars:

status bar visible

When WindowInsetsControllerCompat is uncommented I would expect the content to be drawn behind the status bar and cutout (just like on the picture above) with the status bar icons hidden. Instead I get the black area where nothing is drawn:

status bar hidden

I have confirmed this behavior both on emulator and a physical device.

My question is: using Jetpack Compose, how can I achieve this effect?:

status bar expected behavior


Solution

  • I found a solution here: https://developer.android.com/develop/ui/views/layout/display-cutout#best-practices

    Use shortEdges or never cutout modes if your app needs to transition into and out of immersive mode. Default cutout behavior can cause content in your app to render in the cutout area while the system bars are present, but not while in immersive mode.

    So to allow drawing behind a hidden system bar LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES is required:

        enableEdgeToEdge()
    
        WindowInsetsControllerCompat(window, window.decorView).apply {
            hide(WindowInsetsCompat.Type.statusBars())
            systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        }
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
        }
    
        setContent {
            ...
        }