Handeling status bar and Top App Bar using WindowInsets usind Jetpack Compose.
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:
- Status Bar Insets: These describe the size and position of the status bar, which contains notification icons and indicators.
- 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.
- Caption Bar Insets: These describe system UI window decoration, especially in freeform windows like a top title bar.
- IME (Input Method Editor) Insets: These describe the amount of space occupied by the software keyboard, helping your app adjust content layout accordingly.
- System Gestures Insets: These represent areas where the system intercepts gestures for navigation. Apps can handle limited gestures manually.
- Display Cutout Insets: These represent spacing needed to avoid overlapping with a display cutout like a notch or pinhole.
- 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”
- 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 usingTopAppBarDefaults.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
appliespadding(it)
, whereit
represents the padding values provided by theScaffold
to ensure the content respects the insets. fillMaxSize()
ensures that theSurface
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 theColumn
.verticalArrangement = Arrangement.Center
centers the children vertically within theColumn
.Text(text = "I love Android Jetpack Compose")
displays the text centered within theColumn
.
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!