OnScrollStoppedComp(listState) { val layoutInfo = listState.layoutInfo val visibleItems = layoutInfo.visibleItemsInfo if (visibleItems.isEmpty()) { return@OnScrollStoppedComp }
var selectIndexNew = 0 val centerY = itemHeightPx / 2f // 找到包含 centerY 的那个 item var closestIndex = visibleItems.first().index var minDistance = Float.MAX_VALUE
for (item in visibleItems) { // item.offset 是 item 顶部相对于 viewport 顶部的偏移(可为负) val itemCenterY = item.offset + itemHeightPx / 2f val distance = abs(itemCenterY - centerY) if (distance < minDistance) { minDistance = distance closestIndex = item.index } }
selectIndexNew = closestIndex
onSelectedIndexChange(selectIndexNew) } var itemHeight by remember { mutableStateOf(48.dp) } val density = LocalDensity.current Box( modifier = Modifier .fillMaxSize() .onGloballyPositioned { coordinates -> // 获取布局完成后的像素高度 itemHeight = with(density) { (coordinates.size.height / showItemNum).toDp() } itemHeightPx = with(density) { itemHeight.toPx() } } ) { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { // 中间背景 Box( modifier = Modifier .fillMaxWidth() .height(itemHeight) .background(selectBgColor) ) } LazyColumn( state = listState, contentPadding = PaddingValues(vertical = itemHeight * ((showItemNum - 1) / 2)), verticalArrangement = Arrangement.spacedBy(0.dp), modifier = Modifier.fillMaxSize() ) { items(items.size) { index -> val isSelected = index == selectedIndex Box( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxWidth() .height(itemHeight) .clip(RoundedCornerShape(8.dp)) .graphicsLayer { alpha = if (isSelected) 1felse0.6f scaleX = if (isSelected) 1.1felse1f } ) { Text( text = items[index] + unit, fontSize = if (isSelected) 20.sp else16.sp, fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, color = if (isSelected) Color(0xFF333333) else Color( 0xFF999999 ) ) } } } } }