Desktop Compose中LazyColumn的平滑滚动异常问题
解决LazyColumn鼠标滚轮滚动跳跃问题
问题原因
Compose的LazyColumn默认对鼠标滚轮事件采用按列表项为单位的步进滚动,而非像素级平滑滚动,这直接导致了滚动时的跳跃感。另外,你给每个列表项添加的animateItemPlacement()修饰符,会让项在滚动时执行位置动画,与滚轮的步进逻辑冲突,进一步加剧了不流畅的表现。
解决方案
方案1:自定义像素级平滑滚动行为
通过结合scrollable修饰符与自定义滚动逻辑,替换默认的项级滚动为像素级平滑滚动:
@ExperimentalFoundationApi @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @Composable fun App() { Box(modifier = Modifier.fillMaxSize().padding(10.dp)) { val animatedpr = remember { androidx.compose.animation.core.Animatable(initialValue = 0.8f) } val stateVertical = rememberLazyListState(0) // 自定义滚动状态,处理像素级滚动 val scrollableState = rememberScrollableState { delta -> stateVertical.scrollBy(-delta) delta } LaunchedEffect(Unit) { animatedpr.animateTo(targetValue = 1f, animationSpec = tween(300, easing = LinearEasing)) } LazyColumn( modifier = Modifier .fillMaxSize() .scrollable( state = scrollableState, orientation = Orientation.Vertical, reverseDirection = false ), horizontalAlignment = Alignment.CenterHorizontally, state = stateVertical, flingBehavior = rememberScrollableFlingBehavior(scrollableState) ) { items(1100) { OutlinedCard( modifier = Modifier .size(500.dp, 100.dp) .padding(20.dp) // 建议暂时移除该动画,若需保留可缩短动画时长(如tween(100)) // .animateItemPlacement() .graphicsLayer(scaleY = animatedpr.value, scaleX = animatedpr.value) ) { } } } VerticalScrollbar( modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(), adapter = rememberScrollbarAdapter(scrollState = stateVertical) ) } }
方案2:调整系统滚动步进参数
针对桌面平台,可通过设置系统属性直接调整鼠标滚轮的滚动步进为像素级,无需修改Compose代码:
// 在应用启动时(如main函数入口)添加 System.setProperty("compose.scroll.wheel.pixel.per.scroll", "30")
数值可按需调整,越小的数值滚动越平滑。
额外优化点
- 移除或调整
animateItemPlacement():该动画会干扰滚动节奏,若必须保留,建议将动画时长缩短至100ms以内。 - 优化全局缩放动画:
animatedpr仅在初始化时执行一次缩放,动画完成后可移除graphicsLayer的缩放配置,减少不必要的性能消耗。
内容的提问来源于stack exchange,提问作者nevrozq
相关产品推荐
相关产品推荐

