Jetpack Compose中如何实现两个横向列表按不同速度同步滚动?
实现方案
你原来的实现思路存在问题:同一个rememberScrollState会让两个滚动组件完全绑定偏移量,自然无法实现不同滚动速度。你需要拆分出两个独立的滚动状态,通过状态监听按比例联动即可:
完整实现代码
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Row import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import kotlin.math.roundToInt // 可根据需求调整滚动倍率,这里顶部速度是底部的2倍 private const val SCROLL_RATIO = 2f @Composable fun SpeedDiffScrollRow() { val topScrollState = rememberScrollState() val bottomScrollState = rememberScrollState() // 防止双向监听触发滚动死循环 var isProgrammaticScroll by remember { mutableStateOf(false) } // 监听顶部滚动,按比例驱动底部滚动 LaunchedEffect(topScrollState.value) { if (!isProgrammaticScroll) { isProgrammaticScroll = true val targetBottomOffset = (topScrollState.value / SCROLL_RATIO) .roundToInt() .coerceIn(0, bottomScrollState.maxValue) bottomScrollState.scrollTo(targetBottomOffset) isProgrammaticScroll = false } } // 监听底部滚动,按比例驱动顶部滚动(如果不需要支持滑动底部控制,可删除这段) LaunchedEffect(bottomScrollState.value) { if (!isProgrammaticScroll) { isProgrammaticScroll = true val targetTopOffset = (bottomScrollState.value * SCROLL_RATIO) .roundToInt() .coerceIn(0, topScrollState.maxValue) topScrollState.scrollTo(targetTopOffset) isProgrammaticScroll = false } } Row(modifier = Modifier.horizontalScroll(topScrollState)) { Images() } // 如果不需要支持滑动底部控制,可给horizontalScroll加enabled = false参数 Row(modifier = Modifier.horizontalScroll(bottomScrollState)) { Legend() } }
可选优化
- 如果需要滚动带惯性动画效果,可以把
scrollTo替换为animateScrollTo,注意调整动画时长避免跟手延迟 - 如果只允许用户操作顶部滚动区域,可删除底部滚动的监听逻辑,同时给底部
horizontalScroll添加enabled = false参数,减少不必要的状态监听
内容的提问来源于stack exchange,提问作者axebau24
相关产品推荐
相关产品推荐

