Handeling status bar and Top App Bar using WindowInsets usind Jetpack Compose.

Abhay Kumar Jha
5 min readJun 5, 2024

Jetpack Compose has revolutionized UI development in Android, offering a modern, declarative way to build interfaces. However, as with any new technology, there are occasional hiccups that developers encounter. One such issue is the padding mismatch when using windowInsets in Jetpack Compose's Scaffold component, especially in edge-to-edge enabled scenarios.

The Problem

When you enable edge-to-edge rendering in your Compose application, you might notice that the padding applied by the Scaffold component doesn’t align perfectly with the system windows (status bar, navigation bar, etc.). This can result in UI elements appearing too close to or too far from the edges, leading to a suboptimal user experience.

Understanding WindowInsets

WindowInsets is a feature that allows your app to handle different system UI components dynamically, such as the status bar, navigation bar, and cutouts. With the edge-to-edge display, it's crucial to account for these insets to ensure your content is laid out correctly.

Here’s a breakdown of different types of window insets and their meanings:

  1. Status Bar Insets: These describe the size and position of the status bar, which contains notification icons and indicators.
  2. Navigation Bar Insets: These describe the size and position of navigation bars, which include taskbar or navigation icons. They can change dynamically based on user interaction and device configuration.
  3. Caption Bar Insets: These describe system UI window decoration, especially in freeform windows like a top title bar.
  4. IME (Input Method Editor) Insets: These describe the amount of space occupied by the software keyboard, helping your app adjust content layout accordingly.
  5. System Gestures Insets: These represent areas where the system intercepts gestures for navigation. Apps can handle limited gestures manually.
  6. Display Cutout Insets: These represent spacing needed to avoid overlapping with a display cutout like a notch or pinhole.
  7. Waterfall Insets: These represent curved areas of a waterfall display where the screen begins to wrap along the sides of the device.

The Solution

To manage the padding mismatch, you need to explicitly handle the window insets in your Compose layout. Here’s a step-by-step guide on how to do this:

Lets create an new Jetpack Compose Project with name “topappbarinjetpackcompose”

  1. Enable Edge-to-Edge Mode: Ensure that your activity is set to draw behind system bars by adding the following code in your onCreate method: by calling enableEdgeToEdge()
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TopAppBarInJetpackComposeTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
MainCompose()
}
}
}
}
}

2. Make a new folder inside ui folder name as components

3. Inside this compoenents folder make an kotlin file and name as MainCompose.kt

4. Let’s Start coding inside MainCompose.kt

@Composable
fun MainCompose() {}

The @Composable annotation marks the MainCompose function as a composable function, enabling it to describe UI elements.

5. Inside the MainCompose starts with Scaffold() for creating TopAppBar.

    Scaffold(
contentWindowInsets = WindowInsets.systemBarsIgnoringVisibility,
topBar = {
CenterAlignedTopAppBar(
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
),
title = { Text(text = "Kaam-Kaaj") },
)
}
) {
}

Explanation:

  • Scaffold is a high-level component in Jetpack Compose that provides a framework for organizing UI components, such as top bars, bottom bars, and floating action buttons.
  • contentWindowInsets = WindowInsets.systemBarsIgnoringVisibility is used to handle system window insets (like the status bar and navigation bar) while ignoring their visibility state.
  • CenterAlignedTopAppBar defines a top app bar with centered alignment. The colors are customized using TopAppBarDefaults.centerAlignedTopAppBarColors.

6. Inside the Scaffold declare column which is shows the content inside the Scaffold and here. The important point is padding otherwise the content of Scaffold will move the Upper-Left corner. (modifier = Modifier.padding(it) is important here

        Surface(
modifier = Modifier
.padding(it)
.fillMaxSize()
) {
}

Explanation:

  • Surface is a composable that provides a drawing surface with defined background and elevation.
  • The modifier applies padding(it), where it represents the padding values provided by the Scaffold to ensure the content respects the insets.
  • fillMaxSize() ensures that the Surface fills the maximum available space within its parent.

7. Part 4: Column with Centered Content

            Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(text = "I love Android Jetpack Compose")
}

Explanation:

  • Column is a layout composable that arranges its children in a vertical sequence.
  • horizontalAlignment = Alignment.CenterHorizontally centers the children horizontally within the Column.
  • verticalArrangement = Arrangement.Center centers the children vertically within the Column.
  • Text(text = "I love Android Jetpack Compose") displays the text centered within the Column.

The whole picture of codes look like this

MainActivity.kt

(Note :- Ignore the red underline below the innerpadding. It will not create any issue.)

package com.example.topappbarinjetpackcompose

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.topappbarinjetpackcompose.ui.components.MainCompose
import com.example.topappbarinjetpackcompose.ui.theme.TopAppBarInJetpackComposeTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TopAppBarInJetpackComposeTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
MainCompose()
}
}
}
}
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
TopAppBarInJetpackComposeTheme {
Greeting("Android")
}
}

MainCompose.kt

package com.example.topappbarinjetpackcompose.ui.components

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsIgnoringVisibility
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable
fun MainCompose() {
Scaffold(
contentWindowInsets = WindowInsets.systemBarsIgnoringVisibility,
topBar = {
CenterAlignedTopAppBar(
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
),
title = { Text(text = "Kaam-Kaaj") },
)
}
) {
Surface(
modifier = Modifier
.padding(it).fillMaxSize()
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
)
{
Text(text = "I love Android Jetpack Compose")
}

}
}
}

Result of the Code looks like :-

Top AppBar color may vary because i have not hardcoded the color of container you can change as per your requirement.

Conclusion

By properly managing window insets in your Jetpack Compose application, you can ensure that your UI elements are positioned correctly, even in edge-to-edge scenarios. This not only improves the visual appeal of your app but also enhances the user experience by making sure that content is not obscured by system UI elements.

Keep experimenting with Compose and stay tuned for more updates and best practices as the framework continues to evolve!

--

--