前言
在 Jetpack Compose 中,Row 本身 不支持滚动到某一项。
如果你希望实现横向滚动的布局,并且能够滚动到指定项,你应该使用 LazyRow(而不是普通的 Row)。
注意
普通 Row 放在 HorizontalScrollable 或 Modifier.horizontalScroll() 中虽然可以横向滚动,但 无法精确滚动到某一项,因为没有类似 scrollToItem 的 API。
此时只能通过 scrollState.animateScrollTo(value: Int) 手动计算像素位置,非常不推荐。
完整实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| @Composable fun EchoWordTitleTabComp( titleArr: List<String>, selectTitle: String = "", onClick: (String) -> Unit ) { val listState = rememberLazyListState() val scope = rememberCoroutineScope() LazyRow( state = listState, horizontalArrangement = Arrangement.spacedBy(16.dp) ) { items(titleArr) { title -> Box(modifier = Modifier.clickableDebounced { onClick(title) }) { TitleItemComp(title, isSelected = title == selectTitle) } } } LaunchedEffect(selectTitle) { delay(100) scope.launch { if (selectTitle.isNotEmpty()) { val index = titleArr.indexOf(selectTitle) val visibleItems = listState.layoutInfo.visibleItemsInfo val firstVisibleIndex = visibleItems.firstOrNull()?.index ?: 0 val lastVisibleIndex = visibleItems.lastOrNull()?.index ?: 0 if (index !in firstVisibleIndex..lastVisibleIndex) { listState.scrollToItem(index) } } } } }
|
滚动到指定索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| LaunchedEffect(selectTitle) { delay(100) scope.launch { if (selectTitle.isNotEmpty()) { val index = titleArr.indexOf(selectTitle) val visibleItems = listState.layoutInfo.visibleItemsInfo val firstVisibleIndex = visibleItems.firstOrNull()?.index ?: 0 val lastVisibleIndex = visibleItems.lastOrNull()?.index ?: 0 if (index !in firstVisibleIndex..lastVisibleIndex) { listState.scrollToItem(index) } } } }
|
LazyRow和Row
LazyRow/LazyColumn与Row/Column怎样选择?
个人建议:
只要列表的数据会超出显示区域的,都建议使用LazyRow/LazyColumn,他只会渲染显示的部分,使用Row/Column会出现卡顿。