4

I have a places list that it can be selected via ModalBottomSheetLayout. These places are in a LazyColumn inside the ModalBottomSheetLayout.

When I open the ModalBottomSheetLayout clicking in 'Open place Selector' to select a new place, I would like to scroll to the previous selected place.

If the ModalBottomSheetLayout is halfexpanded the LazyColumn consider the full screen height, and not the ModalBottomSheetLayout halfexpanded height.

Option 1.

  • List size: 18
  • Selected place position: 6

enter image description here

Option 2.

  • List size: 18
  • Selected place position: 15

enter image description here

In case Option 1, when you try to scroll to selected place, it scrolls to previous selected place. Expected behaviour.

In case Option 2, when you try to scroll to selected place, not working.

How can I fix it?

@OptIn(ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class)
@Composable
internal fun PlaceScreen(places: List<String>, selectedPlace: String) {
    val skipHalfExpanded by remember { mutableStateOf(false) }
    val modalBottomSheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden, skipHalfExpanded = skipHalfExpanded)
    val scope = rememberCoroutineScope()
    Surface(modifier = Modifier.nestedScroll(rememberNestedScrollInteropConnection())) {
        ModalBottomSheetLayout(sheetContent = { BottomSheet(places = places, selectedPlace)}, sheetState = modalBottomSheetState) {
            Button(onClick = { scope.launch { modalBottomSheetState.show()}}) {
                Text(text = "Open place selector")
            }
        }
    }
}

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun BottomSheet(places: List<String>, selectedPlace: String) {
    Column {
        val listState = rememberLazyListState()
        Surface(modifier = Modifier.nestedScroll(rememberNestedScrollInteropConnection())) {
            LazyColumn(state = listState) {
                items(places.size) { pos ->
                    Item(place = places[pos], isSelected = places[pos] == selectedPlace)
                }
            }
        }
        LaunchedEffect(key1 = "place", block = {
            listState.animateScrollToItem(index = places.indexOf(selectedPlace))
        })
    }
}

@Composable
fun Item(place: String, isSelected: Boolean) {
    Row(modifier = Modifier.height(60.dp), verticalAlignment = Alignment.CenterVertically) {
        Text(text = place)
        Spacer(modifier = Modifier.weight(1f))
        RadioButton(selected = isSelected, onClick = null)
    }
}
RMH
  • 169
  • 1
  • 14
  • didn't tried to run this yet, but what about additional delay would suffice? modal is shown with animation, so it takes some time to actually see the whole list. What about coroutineScope.launch { delay(1000) listState.animateScrollToItem(index = places.indexOf(selectedPlace)) } or use LaunchedEffect to do it only once – Lukas Oct 25 '22 at 08:14

0 Answers0