如何在Jetpack Compose的LazyRow中找到中间可见项
实现LazyRow中间可见项自动选中
要让LazyRow滚动时中间可见的数字自动选中,核心是通过LazyListState跟踪滚动状态,计算屏幕中心位置并匹配最接近的item。以下是具体实现方案:
步骤1:核心逻辑实现
通过LazyListState获取可见item的布局信息,对比每个item的中心位置与屏幕中心的距离,找到最接近的item作为选中项。使用derivedStateOf可以让选中状态自动跟随滚动变化,避免不必要的重组。
步骤2:完整代码示例
@Composable fun ScrollableAgeSelector( modifier: Modifier = Modifier ) { val numbers = (12..100).toList() val lazyListState = rememberLazyListState() val screenWidth = LocalConfiguration.current.screenWidthDp.dp val screenCenterX = screenWidth / 2 // 自动计算当前屏幕中间的可见数字 val selectedNum by remember { derivedStateOf { val layoutInfo = lazyListState.layoutInfo val visibleItems = layoutInfo.visibleItemsInfo if (visibleItems.isEmpty()) return@derivedStateOf numbers.first() var closestItem: LazyListItemInfo? = null var minDistance = Float.MAX_VALUE visibleItems.forEach { item -> // 计算item的中心坐标(相对于LazyRow起始点) val itemCenter = item.offset + (item.size / 2f) // 计算与屏幕中心的距离 val distance = abs(itemCenter - screenCenterX.toPx()) if (distance < minDistance) { minDistance = distance closestItem = item } } numbers[closestItem?.index ?: 0] } } // 初始滚动到默认选中的数字(比如22) LaunchedEffect(Unit) { val initialIndex = numbers.indexOf(22) lazyListState.scrollToItem(initialIndex) } LazyRow( modifier = modifier.fillMaxWidth(), state = lazyListState, horizontalArrangement = Arrangement.spacedBy(20.dp), // 添加左右内边距,让边缘数字也能滚动到屏幕中间 contentPadding = PaddingValues(horizontal = (screenWidth - 60.dp) / 2) ) { items(numbers.size) { index -> val num = numbers[index] NumberItem( num = num, selectedNum = selectedNum ) } } } // 示例NumberItem组件,根据选中状态切换样式 @Composable fun NumberItem(num: Int, selectedNum: Int) { val isSelected = num == selectedNum Text( text = num.toString(), fontSize = if (isSelected) 24.sp else 18.sp, fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal, color = if (isSelected) Color.Blue else Color.Gray, modifier = Modifier .width(60.dp) .height(60.dp) .background(if (isSelected) Color.LightGray.copy(alpha = 0.5f) else Color.Transparent) .wrapContentSize(Alignment.Center) ) }
关键细节说明
- LazyListState:作为LazyRow的状态容器,提供可见item的布局信息和滚动控制能力
- derivedStateOf:仅当
lazyListState变化时重新计算选中项,优化性能 - contentPadding:确保最边缘的数字也能滚动到屏幕中间,提升交互完整性
- 初始滚动:通过
LaunchedEffect在组件初始化时定位到默认选中的数字,符合用户初始预期
内容的提问来源于stack exchange,提问作者Roony
相关产品推荐
相关产品推荐

