Modal Bottom Sheet with Peek Height

598 Views Asked by At

enter image description here

I had design where bottom sheet is with certain peek height when it is fully collapsed. And fill entire height when it is expanded. How to implement this design using Modal Bottom Sheet (Jetpack Compose M3) ?

            val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false)
            val scope = rememberCoroutineScope()

            Scaffold() {
                WeatherView(api = api)
                ModalBottomSheet(
                        modifier = Modifier.fillMaxSize(),
                        sheetState = sheetState,
                        onDismissRequest = {scope.launch { sheetState.partialExpand() }.invokeOnCompletion {
                            if (sheetState.targetValue == SheetValue.Hidden) {
                            }
                        }},
                        shape = RoundedCornerShape(
                            topStart = 20.dp,
                            topEnd = 20.dp
                        ),
                        containerColor = Color.White.copy(0.2f),
                        dragHandle = {
                            BottomSheetDefaults.DragHandle(
                                width = 48.dp,
                                height = 5.dp,
                                color = Color.Black.copy(0.3f)
                            )
                        }
                    ) {
                        BottomSheetContent()
                    }
                }
        }
1

There are 1 best solutions below

1
On

If I understand your question correct, you have at least 2 options to set height of ModalBottomSheet:

  1. Apply modifier fillMaxHeight to ModalBottomSheet with required fraction if height should be based on percentage:
modifier = Modifier.fillMaxHeight(0.5f) // 50% of height
  1. Apply modifier height to ModalBottomSheet with required height in Dp:
modifier = Modifier.height(80.dp)

Full example with height based on fraction:

@Composable
private fun Content() {
    var bottomSheetIsOpen by rememberSaveable { mutableStateOf(false) }

    Scaffold {
        Column(
            modifier = Modifier
                .padding(it)
                .fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(
                text = "Screen content"
            )
            ElevatedButton(
                onClick = {
                    bottomSheetIsOpen = true
                }
            ) {
                Text(
                    text = "Show BottomSheet"
                )
            }
        }
    }

    if (bottomSheetIsOpen) {
        BottomSheet(
            closeBottomSheet = {
                bottomSheetIsOpen = false
            }
        )
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun BottomSheet(
    closeBottomSheet: () -> Unit
) {
    val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
    val coroutineScope = rememberCoroutineScope()

    ModalBottomSheet(
        modifier = Modifier.fillMaxHeight(0.5f),
        sheetState = sheetState,
        onDismissRequest = closeBottomSheet
    ) {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(
                text = "BottomSheet content"
            )
            ElevatedButton(
                onClick = {
                    coroutineScope.launch {
                        sheetState.hide()
                    }.invokeOnCompletion {
                        closeBottomSheet()
                    }
                }
            ) {
                Text(
                    text = "Close"
                )
            }
        }
    }
}

Result:

enter image description here