问题描述
之前使用 Compose 定制了一个 iOS 风格的滚轮选择器,禁用了 OverScroll 效果后还原度还算高。但是升级到 Compose 1.9.0 之后发现出问题了。
问题发生在边界 Item 的选中上,我的逻辑是监听 LazyListState.isScrollInProgress,滚动停止时计算并更新当前选中项,同时颜色变化,升级后的问题表现为:
- 缓慢拖动到边界 Item 没有问题
- 快速滑动到边界 Item 触发 fling 后会过很久才会变更选中项
解决方案
在 Application.onCreate() 中调用
ComposeFoundationFlags.isFlingContinuationAtBoundsEnabled = false
排查过程
查看官网更新日志
找半天 1.9.0 更新日志发现提都没提(反正我没找到)
谷歌搜索类似问题
石沉大海,也许不好描述
看源码(READ THE FUCKING SOURCE CODE)
跟踪 LazyListState.isScrollInProgress 值的 set 方法发现是 ScrollableState.scroll 方法中触发的,而 LazyListState.scroll 中会调用它。
断点发现,scroll 是 doFlingAnimation 触发的,既然问题出在 Fling 那么肯定是它有问题。
从 Maven Repo 下载 1.8.3 和 1.9.0 两个版本的 Compose Foundation 源码,对比发现,新版本判断是否取消 Fling 前会先判断一个新的名为 isFlingContinuationAtBoundsEnabled的全局变量
更多探索
断点发现doFlingAnimation 它其实是ScrollableNode.onDragStopped触发的。
不用想,LazyColumn 肯定是一个 ScrollableNode。
查看源码可以发现,它是通过 Modifier.scrollingContainer 创建一个了 ScrollingContainerElement,而它创建了 ScrollingContainerNode,这个 Node 在 onAttach 的时候又会创建一个 ScrollableNode,再里面就...太复杂了,没有看。
LazyLayout(
modifier =
modifier
...
.scrollingContainer(
state = state,
...
),
...
)