美文网首页
【Android】使用 LazyColumn 进行视差滚动

【Android】使用 LazyColumn 进行视差滚动

作者: 安安_660c | 来源:发表于2022-08-22 15:26 被阅读0次

视差滚动效果总是很好看,它会引起用户的注意。使用 Jetpack Compose 可以很容易地实现这个效果。

只是另一个项目

在示例中,我们在带有文本项的列表顶部有一个图像。这可能意味着我们有一个 Image 后跟一个LazyColumn,但是在查看 API LazyColumn时,我们不仅可以调用items方法并给它一个包含数据的列表来创建我们的项目。

val list = (0..1_000).map{ "Item $it" }.toList()

LazyColumn {
    items(list) { item ->
        Text(text = item)
    }
}

我们还可以在LazyColumn的范围内调用多个itemitems方法。它不仅限于让它调用items函数。 为此,我们可以使用item来显示图像,然后使用items来创建列表。

val list = (0..1_000).map{ "Item $it" }.toList()

LazyColumn {

    item {
        Image(
            painter = resourcePainter(id = R.drawable.image),
            contentDescription = "Top image"),
            contentScale = ContentScale.Crop,
            modifier = Modifier.fillParentMaxWidth()
    }

    items(list) { item ->
        Text(text = item)
    }
}

有了这个,我们已经有了一个包含两种类型项目的列表,当然现在它们正在以相同的速度滚动。

没那么快

为了达到视差效果,我们需要降低图像的滚动速度,同时保持其他项目的滚动速度不变。

为了影响我们需要的滚动

  1. 一种获取滚动信息的方法
  2. 一种操纵图像滚动行为的方法。

对于滚动信息,我们可以利用LazyColumns参数LazyListState,它包含我们需要的信息。为了实现它,我们不保留默认值,而是创建自己的并将其传入。

val lazyListState = rememberLazyListState()

LazyColumn(state = lazyListState){
    ...
}

LazyListState派生,与其他项相比,我们可以计算图像沿 y 轴的较慢平移。

val firstItemTranslationY by remember {
        derivedStateOf {
            when {
                lazyListState.layoutInfo.visibleItemsInfo.isNotEmpty() && lazyListState.firstVisibleItemIndex == 0 -> lazyListState.firstVisibleItemScrollOffset * .6f
                else                                                                                               -> 0f
            }
        }
    }

我们检查图像是否在屏幕上可见,如果不是,我们不想做任何事情,只是说正常,通过返回 0 的平移。只要图像可见,我们就获取当前的滚动偏移量并将其乘以一个介于 1 和 0 之间的数字。数字越接近 1,图像随着滚动移动的速度越慢。对于视差滚动效果,我们希望图像在屏幕上保持更长时间,就像通常那样。

您可以随意使用该值来调整速度。对于此示例,让我们将其保持在中间的某个位置,即 0.6。

现在我们有了调整图像滚动的价值。但是应该在哪里应用呢?为此,Compose 提供了一个非常方便的修改器,我们可以使用它。Modifier.graphicsLayer为我们提供了操作缩放、旋转、alpha、平移和更多应用它的 Composable 的可能性。

翻译听起来是个不错的选择。让我们将Modifier.graphicsLayer应用于我们的图像并将垂直平移设置为我们刚刚计算的值。

...
item {
    Image(
        painter = painterResource(id = R.drawable.image),
        contentDescription = "Top image",
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .fillParentMaxWidth()
            .graphicsLayer {
                translationY = firstItemTranslationY
            }
    )
}
...

只是为了多玩一点,让我们在滚动时慢慢淡出图像。

val visibility by remember {
        derivedStateOf {
            when {
                lazyListState.layoutInfo.visibleItemsInfo.isNotEmpty() && lazyListState.firstVisibleItemIndex == 0 -> {
                    val imageSize = lazyListState.layoutInfo.visibleItemsInfo[0].size
                    val scrollOffset = lazyListState.firstVisibleItemScrollOffset

                    scrollOffset / imageSize.toFloat()
                }
                else                                                                                               -> 1f
            }
        }
    }

该过程与之前基本相同,不同之处在于不是取第一项的偏移量,而是取其大小和滚动偏移量并计算 alpha 值。

当我们应用它时,我们从 1 中减去我们计算的可见性,图像在离开屏幕时将是完全透明的。

.graphicsLayer {
    alpha = 1f - visibility
    translationY = firstItemTranslationY
}

结论

使用 Jetpack 组合 LazyColumn 和Modifier.graphicsLayer,创建视差滚动效果非常简单。计算从LazyListState派生的翻译并将其应用于Modifier

整个代码可以在GitHub上找到。

我还在这个例子中添加了一个褪色的 TopBar。我希望后退箭头始终可见,因此最终创建了我自己的 TopBar。如果您对如何使其与标准 Compose TopBar 一起工作有任何想法,请发表评论或直接写信给我。我想听听:-)。

希望你喜欢这个关于视差滚动的小例子。
下期见👋。

链接:https://dev.to/lex_fury/parallax-scrolling-using-lazycolumn-4934

相关文章

网友评论

      本文标题:【Android】使用 LazyColumn 进行视差滚动

      本文链接:https://www.haomeiwen.com/subject/rceigrtx.html