Accompanist FlowRow如何实现自动滚动到指定索引的元素?
实现方案
你可以通过记录每个子元素在FlowRow中的位置偏移,在组件首次渲染完成后触发滚动,具体修改步骤如下:
核心思路
- 存储每个索引对应子元素的垂直偏移量
- 组件首次组合完成后,读取目标索引的偏移量,触发滚动到对应位置
- 滚动状态绑定保持不变,不影响用户后续手动滚动操作
修改后的完整代码
import androidx.compose.foundation.gestures.animateScrollTo import androidx.compose.foundation.layout.onGloballyPositioned import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember sealed class MovesNavigatorElement(open val text: String) data class MoveNumber(override val text: String) : MovesNavigatorElement(text) data class HalfMoveSAN(override val text: String) : MovesNavigatorElement(text) @Composable fun MovesNavigator(modifier: Modifier = Modifier, elements: Array<MovesNavigatorElement>, mustBeVisibleByDefaultElementIndex: Int) { val vertScrollState = rememberScrollState() // 存储每个子元素在FlowRow中的顶部Y偏移量 val itemOffsets = remember { mutableStateListOf<Int>() } FlowRow( modifier = modifier .background(color = Color.Yellow.copy(alpha = 0.3f)) .verticalScroll(vertScrollState), mainAxisSpacing = 10.dp, crossAxisSpacing = 15.dp, ) { elements.forEachIndexed { index, element -> Text( text = element.text, fontSize = 34.sp, color = Color.Blue, style= MaterialTheme.typography.body1, modifier = Modifier.onGloballyPositioned { coordinates -> // 记录当前元素在父容器中的相对Y偏移,不受滚动偏移影响 val yOffset = coordinates.positionInParent().y.toInt() if (index >= itemOffsets.size) { itemOffsets.add(yOffset) } else { itemOffsets[index] = yOffset } } ) } } // 所有子元素偏移收集完成后触发一次滚动 LaunchedEffect(itemOffsets.size) { if (itemOffsets.size == elements.size && mustBeVisibleByDefaultElementIndex in elements.indices) { val targetOffset = itemOffsets[mustBeVisibleByDefaultElementIndex] // 不需要平滑滚动可替换为scrollTo方法 vertScrollState.animateScrollTo(targetOffset) } } }
补充说明
- 如果需要保证目标元素完全在可视区域内,可以在
onGloballyPositioned中同时记录每个元素的高度,滚动时结合容器可视高度调整偏移量即可 - 如果你使用的是Compose 1.4及以上版本的官方原生
FlowRow,该实现逻辑完全通用 - 上述逻辑只会在组件首次挂载、布局完成后执行一次自动滚动,后续用户手动操作滚动条不会被自动滚动打断
内容的提问来源于stack exchange,提问作者loloof64
相关产品推荐
相关产品推荐

