4

I'm trying to use Compose to apply the shadow that's applied to the background when you open a bottom sheet to the status bar as well, example here (Google News app). The whole background, including the status bar gets a shadow, but I can't replicate the same behaviour in a simple app. I've bee using the ModalBottomSheetLayout composable to invoke the bottom sheet.

Google News app with a bottom sheet opened

I've tried using the accompanist library and its System UI Controller to set the color of the status bar to Transparent, but maybe I'm misunderstanding what that's meant to do, as the status bar just remains white and unchanged when the bottom sheet is opened.

How can I put the status bar "in the background" as well when a bottom sheet is opened?

Martyna Maron
  • 371
  • 4
  • 19
  • This is the same as [this question](https://stackoverflow.com/q/69560253/9636037). But unfortunately, there is no correct answer there till now. – Abhimanyu May 05 '22 at 01:35
  • 2
    Thanks @Abhimanyu! I actually raised [an issue](https://issuetracker.google.com/issues/231606426) for this, because the view-based [BottomSheetDialogFragment](https://developer.android.com/reference/com/google/android/material/bottomsheet/BottomSheetDialogFragment) applies the shadow to the status bar out of the box. I think it's missed functionality in the Compose one! – Martyna Maron May 06 '22 at 16:14
  • Does this answer your question? [Modal Bottom Sheet scrim color is not shown in status bar in Jetpack compose](https://stackoverflow.com/questions/69560253/modal-bottom-sheet-scrim-color-is-not-shown-in-status-bar-in-jetpack-compose) – DmitryBorodin Sep 28 '22 at 20:13

3 Answers3

0

There is a question asked before, but I will keep my old answer here as well. Modal Bottom Sheet scrim color is not shown in status bar in Jetpack compose

Keeping here old answer as it may be relevant to somebody, new in a link above ^^

Approach below is Deprecated, one above it not

You need a dependency

implementation "com.google.accompanist:accompanist-insets:0.17.0"

put app content in ProvideWindowInsets

setContent {
    ProvideWindowInsets {
        AppContent()
    }
}

then add Modifier.navigationBarsWithImePadding() to the content of Bottom sheet like this

ModalBottomSheetLayout(
    sheetContent = { SheetContent(Modifier.navigationBarsWithImePadding()) },
    sheetState = sheetState,
    sheetBackgroundColor = Color.Black
) {}

Sample https://github.com/lbenevento/compose-modalbottomsheet

DmitryBorodin
  • 4,584
  • 4
  • 17
  • 29
0

Solution for 2023:

    @Composable
    fun ModalStatusBarBottomSheetLayout(
        sheetContent: @Composable ColumnScope.() -> Unit,
        modifier: Modifier = Modifier,
        sheetState: ModalBottomSheetState =
            rememberModalBottomSheetState(ModalBottomSheetValue.Hidden),
        sheetShape: Shape = MaterialTheme.shapes.large,
        sheetElevation: Dp = ModalBottomSheetDefaults.Elevation,
        sheetBackgroundColor: Color = MaterialTheme.colors.surface,
        sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
        scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
        content: @Composable () -> Unit
    ): Unit = ModalBottomSheetLayout(
        sheetContent = sheetContent,
        modifier = modifier,
        sheetState = sheetState,
        sheetShape = sheetShape,
        sheetElevation = sheetElevation,
        sheetBackgroundColor = sheetBackgroundColor,
        sheetContentColor = sheetContentColor,
        scrimColor = scrimColor
    ) {
        val context = LocalContext.current
        var statusBarColor by remember { mutableStateOf(Color.Transparent) }
        val backgroundColor = remember {
            val typedValue = TypedValue()
            if (context.findActivity().theme
                    .resolveAttribute(android.R.attr.windowBackground, typedValue, true)
            ) {
                Color(typedValue.data)
            } else {
                sheetBackgroundColor
            }
        }
        
        Box(modifier = Modifier
            .fillMaxWidth()
            .background(statusBarColor)
            .statusBarsPadding()) {
            Box(modifier = Modifier
                .background(backgroundColor)
                .fillMaxSize()
                .navigationBarsPadding()) {
                content()
            }
        }

        DisposableEffect(Unit) {
            val window = context.findActivity().window
            val originalStatusBarColor = window.statusBarColor
            statusBarColor = Color(originalStatusBarColor)

            window.statusBarColor = TRANSPARENT
            WindowCompat.setDecorFitsSystemWindows(window, false)

            onDispose {
                window.statusBarColor = originalStatusBarColor
                WindowCompat.setDecorFitsSystemWindows(window, true)
            }
        }
    }

Usage:

val state = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
val scope = rememberCoroutineScope()
ModalStatusBarBottomSheetLayout(
           sheetState = state,
           modifier = Modifier.fillMaxSize(),
           sheetContent = {
                Text(modifier = Modifier
                       .fillMaxWidth()
                       .height(250.dp), 
                     text = "BOTTOM SHEET CONTENT")
                }
    ) {
        Button(onClick = {
            scope.launch {
               state.show()
            }
        }) {
              Text(text = "SHOW BOTTOM SHEET")
           }
    }

Here is findActivity implementation.

Arsenius
  • 4,972
  • 4
  • 26
  • 39
-1

Call this in onCreate function;

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

        //Call this
        WindowCompat.setDecorFitsSystemWindows(window, false)

        setContent {

            AppTheme {

                MainScreen()
            }
        }
    }
}
commandiron
  • 1,019
  • 1
  • 9
  • 25
  • That's one way of achieving this, but I don't actually want my app to be full screen - the Google News app doesn't seem to be either. – Martyna Maron May 06 '22 at 15:15
  • you don't have to, you can easily set padding value from top with the status bar height. However you may not want this solution. – commandiron May 06 '22 at 21:42