androidkotlinandroid-jetpack-compose

How can I set sheetPeekHeight to the height of an item inside it in Jetpack Compose?


Given the example

BottomSheetScaffold(
    sheetContent = {
        LazyColumn(
            state = listState,
            contentPadding = PaddingValues(8.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            items(data.items) {
                Card(modifier = Modifier.fillMaxWidth()) {
                    Column {
                        Text(text = it.title)
                        Text(text = it.subtitle)
                        Spacer(modifier = Modifier.height(8.dp))
                        Text(text = it.image)
                    }
                }
            }
        }
    },
    sheetPeekHeight = [...]
) {

}

How can I set sheetPeekHeight to be, for example, 40% of the first Card in the LazyColumn within?


Solution

  • You can try something like:

    // Need to remember to allow the value changing to mutate the BottomSheet input variable
    var peekHeightPx by remember { mutableStateOf(0) }
    
    BottomSheetScaffold(
        sheetContent = {
            LazyColumn(
                state = listState,
                contentPadding = PaddingValues(8.dp),
                verticalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                var index = 0
                items(data.items) {
                    Card(modifier = Modifier
                        .fillMaxWidth()
                        .onGloballyPositioned {
                            if (index++ == 0) {
                                peekHeightPx = (it.size.height * 0.4f).toInt()
                            }
                        }) {
                        Column {
                            Text(text = it.title)
                            Text(text = it.subtitle)
                            Spacer(modifier = Modifier.height(8.dp))
                            Text(text = it.image)
                        }
                    }
                }
            }
        },
        // If we don't have a value yet, just render it at the default value
        sheetPeekHeight = if (peekHeightPx == 0) {
            BottomSheetScaffoldDefaults.SheetPeekHeight
        } else {
            // The value from onGloballyPositioned is in px and needs to be converted back to a dp value, and 8 needs to be added for the padding and 8 for the spacing between
            (with(LocalDensity.current) { peekHeightPx / density } + 16).dp
        }
    ) {
    
    }