What is the proper way to get status bar height in compose?

Viewed 2104

Usually when using Accompanist Modifier.statusBarsHeight() the height will change depends on the status bar visibility, if it's visible either 24.dp or more and if it's invisible the height will be 0.dp. But i want the height won't change to zero regardless of its visibility.

I've been using this for a while:

// TODO: use better solution to get a fixed status bar height
val statusBarHeight = with (LocalDensity.current) { LocalWindowInsets.current.statusBars.top.toDp() }
val fixedStatusBarHeight = remember { statusBarHeight }
2 Answers

So i ended up making a workaround alongside with a modifier extension for easier use.

First, make a data class to hold the fixed inset values.

data class FixedInsets(
    val statusBarHeight: Dp = 0.dp,
    val navigationBarsPadding: PaddingValues = PaddingValues(),
)

Second, create the extension and a composition local provider.

val LocalFixedInsets = compositionLocalOf<FixedInsets> { error("no FixedInsets provided!") }

@Composable
fun Modifier.fixedStatusBarsPadding(): Modifier {
    return this.padding(top = LocalFixedInsets.current.statusBarHeight)
}

@Composable
fun Modifier.fixedNavigationBarsPadding(): Modifier {
    return this.padding(paddingValues = LocalFixedInsets.current.navigationBarsPadding)
}

Finally, provide the fixed inset values at the very root of your composable function.

val systemBarsPadding = WindowInsets.systemBars.asPaddingValues()
val fixedInsets = remember {
    FixedInsets(
        statusBarHeight = systemBarsPadding.calculateTopPadding(),
        navigationBarsPadding = PaddingValues(
            bottom = systemBarsPadding.calculateBottomPadding(),
            start = systemBarsPadding.calculateStartPadding(LayoutDirection.Ltr),
            end = systemBarsPadding.calculateEndPadding(LayoutDirection.Ltr),
        ),
    )
}

CompositionLocalProvider(
    values = arrayOf(
        LocalFixedInsets provides fixedInsets,
    ),
) {
    MainScreen()
}

Navigation bar padding example:

Text(
    text = "Hello i'm a text with navigation bar padding",
    modifier = Modifier
        .fillMaxSize()
        .background(color = Color.Red)
        .fixedNavigationBarsPadding(),
)

Or you can access the sizes in Dp directly from the local composition by using calculateXPadding():

val fixedInsets = LocalFixedInsets.current

Text(
    text = "The navigation bar's height is: ${fixedInsets.navigationBarsPadding.calculateBottomPadding()}",
)

The problem is getting complicated you should use it like this

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .statusBarsPadding().navigationBarsPadding()
        ) {

        }

        Box(
            modifier = Modifier
                .fillMaxSize()
                .statusBarsPadding().systemBarsPadding()
        ) {

        }
    }
}

}

Related