Jetpack Compose 滚动条
Posted
技术标签:
【中文标题】Jetpack Compose 滚动条【英文标题】:Jetpack Compose Scrollbars 【发布时间】:2021-05-26 05:41:45 【问题描述】:有没有办法添加滚动条来添加LazyColumn
(ScrollableColumn
已弃用)。 Javadoc 没有提及 Jetpack Compose 中的滚动条。
澄清一下,这是我要实现的设计:
是否有可能在 Jetpack Compose 中做到这一点?还是不支持滚动条?
【问题讨论】:
Compose-android 上尚不支持滚动条,但现在可用于 Compose-Desktop。 【参考方案1】:这实际上是可能的(他们已经在 LazyListState 中添加了更多的东西)而且很容易做到。这是一个非常原始的滚动条(始终可见/无法拖动/等),它使用项目索引来确定拇指位置,因此在只有少数项目的列表中滚动时它可能看起来不太好:
@Composable
fun Modifier.simpleVerticalScrollbar(
state: LazyListState,
width: Dp = 8.dp
): Modifier
val targetAlpha = if (state.isScrollInProgress) 1f else 0f
val duration = if (state.isScrollInProgress) 150 else 500
val alpha by animateFloatAsState(
targetValue = targetAlpha,
animationSpec = tween(durationMillis = duration)
)
return drawWithContent
drawContent()
val firstVisibleElementIndex = state.layoutInfo.visibleItemsInfo.firstOrNull()?.index
val needDrawScrollbar = state.isScrollInProgress || alpha > 0.0f
// Draw scrollbar if scrolling or if the animation is still running and lazy column has content
if (needDrawScrollbar && firstVisibleElementIndex != null)
val elementHeight = this.size.height / state.layoutInfo.totalItemsCount
val scrollbarOffsetY = firstVisibleElementIndex * elementHeight
val scrollbarHeight = state.layoutInfo.visibleItemsInfo.size * elementHeight
drawRect(
color = Color.Red,
topLeft = Offset(this.size.width - width.toPx(), scrollbarOffsetY),
size = Size(width.toPx(), scrollbarHeight),
alpha = alpha
)
更新: 我已经更新了代码。我已经弄清楚如何在滚动或不滚动 LazyColumn 时显示/隐藏滚动条 + 添加淡入/淡出动画。我还将 drawBehind() 更改为 drawWithContent(),因为前者在内容后面绘制,因此在某些情况下它可能会绘制在滚动条的顶部,这很可能是不可取的。
【讨论】:
有趣的方法,但在我与组合分页库结合使用时,滚动条会永久改变高度,并且滚动看起来很糟糕。即使有 200 件商品。 是的,这很可能是因为state.layoutInfo.visibleItemsInfo
不断变化(这取决于项目的高度差异有多大)。我认为,如果您不按原样使用visibleItemsInfo.size
,而是重新计算可见项目的平均数量,它应该会变得更加平滑。 RecyclerView 在内部做类似的计算来绘制滚动条。
我不知道 drawBehind 修饰符是否没有真正优化,或者它是否与 LazyColumn 有关,但是一旦我添加滚动条,整个列表就比以前更加滞后。在 compose 准备好投入生产之前,他们必须在很多方面提高性能。
是这样的: LazyVerticalGrid( state = state, cells = GridCells.Adaptive(300.dp), modifier = Modifier .fillMaxSize() .simpleVerticalScrollbar(state) ) ... 跨度>
您需要使用与传递给 LazyColumn 相同的 LazyListState。【参考方案2】:
这在LazyColumn
/LazyRow
中尚无法实现。
计划在某个时候添加,但目前还没有具体的计划发布。如果可能,我会更新这个答案。
【讨论】:
这正是为什么 compose 不应该被认为是稳定的或 1.0 直到它达到 XML 视图所具有的功能的奇偶性的原因。这不是我第一次遇到永远存在于 XML 视图中的基本函数,只是为了发现“在 compose 中还不可能”。从谷歌推广这样一个未完成的产品的可怕方式。【参考方案3】:这可能会有所帮助:https://github.com/sahruday/Carousel 一种将 Compose 作为 Composable 函数的类似方法。
适用于CarouselScrollState
(在ScrollState
上添加的参数)和LazyList
。
如果高度变化或混合项目,我不建议添加滚动指示器。
【讨论】:
以上是关于Jetpack Compose 滚动条的主要内容,如果未能解决你的问题,请参考以下文章
删除 Jetpack Compose 中的 LazyColumn 过度滚动效果
Jetpack Compose LazyColumn 以编程方式滚动到项目
viewpager jetpack compose 中的垂直滚动不起作用