androidandroid-jetpack-composeandroid-jetpack-compose-lazy-column

Finding the middle visible item in LazyRow


I have a scrollable LazyRow that contains numbers, I want for the middle visible number to be automatically selected as shown below:

enter image description here

How could I find the middle visible item in a LazyRow?

code:

@Composable
fun ScrollableAgeSelector(
    modifier: Modifier = Modifier
) {

    val numbers = (12..100).toList()

 
    LazyRow(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.spacedBy(20.dp)
    ) {
        items(numbers.size) { index ->
            val num = numbers[index]
            NumberItem(
                num = num,
                selectedNum = 22
            )
        }
    }
}

Solution

  • You can calculate which item is in the center.

    Something like:

        val state = rememberLazyListState()
        LazyRow(state = state) {
            itemsIndexed(itemsList) { index, item ->
                MyItem(
                    state,
                    index,
                    //content = 
                )
            }
        }
    

    With:

    @Composable
    fun MyItem(state: LazyListState, index: Int, /* content */) {
    
        val borderColor by remember {
            derivedStateOf {
    
                val layoutInfo = state.layoutInfo
                val visibleItemsInfo = layoutInfo.visibleItemsInfo
                val itemInfo = visibleItemsInfo.firstOrNull { it.index == index}
    
                itemInfo?.let {
    
                    val delta = it.size/2 //use your custom logic
                    val center = state.layoutInfo.viewportEndOffset / 2
                    val childCenter = it.offset + it.size / 2
                    val target = childCenter - center
                    if (target in -delta..delta) return@derivedStateOf Red
                }
                Transparent
            }
        }
    
        Box(
            Modifier
                .padding(4.dp)
                .width(65.dp)
                .height(120.dp)
                .background(Yellow)
                .border(1.dp, borderColor),
            contentAlignment = Alignment.Center
        ){
            //content
        }
    
    }
    

    enter image description here