I am using Kotlin v1.7.20 and androidx.compose.material3
implementation v1.3.0-beta04.
I need to fit a content into a bottom sheet. This content is so long, and its height exceeds the device’s height that I am using to run the app.
When I deal with non-bottom sheet composable elements, I can easily achieve scrolling of vertically overflown content by wrapping a Column
composable element around the long content, and then applying the following argument into the Column
element:
Column( modifier = Modifier.verticalScroll(state = rememberScrollState()) ) {}
However, this method did not work with ModalBottomSheet
. After expanding the bottom sheet to its full (device’s) height, swiping up the ModalBottomSheet
did not scroll down the long content wrapped in the Column
composable element. (In fact, upon full expansion, ModalBottomSheet
did not respond to any swipe-up gesture.)
Below is the code I used:
// Controls, from an outside composable, whether the modal bottom sheet should be displayed
var showBottomSheet = mutableStateOf(false)
@Composable
@ExperimentalMaterial3Api
@OptIn(ExperimentalMaterial3Api::class)
fun getBottomSheet() {
val scrollState = rememberScrollState()
val sheetState = rememberModalBottomSheetState()
if (showBottomSheet.value) {
ModalBottomSheet(
onDismissRequest = { showBottomSheet.value = false },
sheetState = sheetState,
modifier = Modifier.fillMaxHeight()
) {
Column (
modifier = Modifier.fillMaxHeight().verticalScroll(scrollState)
) {
// Example: generating a vertically very long content
var i: Int
for (i in 1..50) {
Text("Hello", fontSize = 96.sp)
Text("World!", fontSize = 96.sp)
}
}
}
}
}
As per this post, I have tried wrapping a scrollable Column
element around the ModalBottomSheet
(instead of the Column
element being inside the bottom sheet). The bottom sheet still could not scroll into the rest of the long content below. Then another post suggests to use BottomSheetScaffold
in place of ModalBottomSheet
, which offers more advanced functionalities. However, BottomSheetScaffold
messed up with the existing Scaffold
element I already set up in the app’s main composable, so I decided not to use it.
How to achieve vertical scrolling of a long content in a fully expanded ModalBottomSheet
?
I suppose that replacing scrollable Column
with LazyVerticalGrid
could resolve the problem. LazyVerticalGrid
has a built-in vertical scrollability, so the following argument should not be passed when using a LazyVerticalGrid
element in Jetpack Compose:
Modifier.verticalScroll(scrollState)
In addition, beware that you should not place a LazyVerticalGrid
element inside a scrollable Column
composable. See this post; nested scrollables are unstable in Jetpack Compose.
Rewriting your code above, this is how you can make a long content inside a bottom sheet scrollable:
// Controls, from an outside composable,
// whether the modal bottom sheet should be displayed
var showBottomSheet = mutableStateOf(false)
@Composable
@ExperimentalMaterial3Api
@OptIn(ExperimentalMaterial3Api::class)
fun getBottomSheet() {
val sheetState = rememberModalBottomSheetState()
if (showBottomSheet.value) {
ModalBottomSheet(
onDismissRequest = { showBottomSheet.value = false },
sheetState = sheetState,
modifier = Modifier.fillMaxHeight()
) {
val spanSize = 10
LazyVerticalGrid (column = spanSize) {
// Example: generating a vertically very long content
var i: Int
for (i in 1..50) {
item {
Text("Hello", fontSize = 96.sp)
}
// Use "span" argument if you want the child element
// to fill the entire width of the bottom sheet
item(span = { GridItemSpan(spanSize) }) {
Text("World!", fontSize = 96.sp)
}
}
}
}
}
}