Jetpack Compose 滚动条

Posted

技术标签:

【中文标题】Jetpack Compose 滚动条【英文标题】:Jetpack Compose Scrollbars 【发布时间】:2021-05-26 05:41:45 【问题描述】:

有没有办法添加滚动条来添加LazyColumnScrollableColumn 已弃用)。 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 分页)

Jetpack Compose LazyColumn 以编程方式滚动到项目

viewpager jetpack compose 中的垂直滚动不起作用

如何在 Jetpack Compose 的 LazyColumn/LazyRow 中禁用和启用滚动?

Jetpack Compose之手势使用