视差滚动效果总是很好看,它会引起用户的注意。使用 Jetpack Compose 可以很容易地实现这个效果。
只是另一个项目
在示例中,我们在带有文本项的列表顶部有一个图像。这可能意味着我们有一个 Image 后跟一个LazyColumn,但是在查看 API LazyColumn时,我们不仅可以调用items方法并给它一个包含数据的列表来创建我们的项目。
val list = (0..1_000).map{ "Item $it" }.toList()
LazyColumn {
items(list) { item ->
Text(text = item)
}
}
我们还可以在LazyColumn的范围内调用多个item和items方法。它不仅限于让它调用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)
}
}
有了这个,我们已经有了一个包含两种类型项目的列表,当然现在它们正在以相同的速度滚动。
没那么快
为了达到视差效果,我们需要降低图像的滚动速度,同时保持其他项目的滚动速度不变。
为了影响我们需要的滚动
- 一种获取滚动信息的方法
- 一种操纵图像滚动行为的方法。
对于滚动信息,我们可以利用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
网友评论