Skip to content

Commit 8744792

Browse files
implement multilayer parallax scroll effect
Took 50 minutes
1 parent 43c20cc commit 8744792

File tree

1 file changed

+44
-4
lines changed
  • app/src/main/java/xyz/teamgravity/multilayerparallaxscrolleffect

1 file changed

+44
-4
lines changed

app/src/main/java/xyz/teamgravity/multilayerparallaxscrolleffect/MainActivity.kt

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package xyz.teamgravity.multilayerparallaxscrolleffect
22

3+
import android.content.res.Resources
34
import android.os.Bundle
45
import androidx.activity.ComponentActivity
56
import androidx.activity.compose.setContent
@@ -16,8 +17,13 @@ import androidx.compose.runtime.setValue
1617
import androidx.compose.ui.Alignment
1718
import androidx.compose.ui.Modifier
1819
import androidx.compose.ui.draw.clipToBounds
20+
import androidx.compose.ui.geometry.Offset
1921
import androidx.compose.ui.graphics.Brush
2022
import androidx.compose.ui.graphics.Color
23+
import androidx.compose.ui.graphics.graphicsLayer
24+
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
25+
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
26+
import androidx.compose.ui.input.nestedscroll.nestedScroll
2127
import androidx.compose.ui.layout.ContentScale
2228
import androidx.compose.ui.platform.LocalConfiguration
2329
import androidx.compose.ui.res.painterResource
@@ -39,8 +45,32 @@ class MainActivity : ComponentActivity() {
3945
val imageHeight = (LocalConfiguration.current.screenWidthDp * (2f / 3f)).dp
4046
val lazyListState = rememberLazyListState()
4147

48+
val nestedScrollConnection = remember {
49+
object : NestedScrollConnection {
50+
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
51+
val delta = available.y
52+
53+
// check if first item or last
54+
if (lazyListState.firstVisibleItemIndex == 0) {
55+
return Offset.Zero
56+
}
57+
58+
val layoutInfo = lazyListState.layoutInfo
59+
if (layoutInfo.visibleItemsInfo.lastOrNull()?.index == layoutInfo.totalItemsCount - 1) {
60+
return Offset.Zero
61+
}
62+
63+
moonOffset += delta * moonScrollSpeed
64+
midOffset += delta * midScrollSpeed
65+
return Offset.Zero
66+
}
67+
}
68+
}
69+
4270
LazyColumn(
43-
modifier = Modifier.fillMaxSize(),
71+
modifier = Modifier
72+
.fillMaxSize()
73+
.nestedScroll(nestedScrollConnection),
4474
state = lazyListState
4575
) {
4676
items(10) {
@@ -57,23 +87,31 @@ class MainActivity : ComponentActivity() {
5787
modifier = Modifier
5888
.clipToBounds()
5989
.fillMaxWidth()
60-
.height(imageHeight)
90+
.height(imageHeight + midOffset.toDp())
6191
.background(Brush.verticalGradient(listOf(Color(0xFFf36b21), Color(0xFFf9a521))))
6292
) {
6393
Image(
6494
painter = painterResource(id = R.drawable.ic_moon),
6595
contentDescription = "moon",
6696
contentScale = ContentScale.FillWidth,
6797
alignment = Alignment.BottomCenter,
68-
modifier = Modifier.matchParentSize()
98+
modifier = Modifier
99+
.matchParentSize()
100+
.graphicsLayer {
101+
translationY = moonOffset
102+
}
69103
)
70104

71105
Image(
72106
painter = painterResource(id = R.drawable.ic_mid),
73107
contentDescription = "mid",
74108
contentScale = ContentScale.FillWidth,
75109
alignment = Alignment.BottomCenter,
76-
modifier = Modifier.matchParentSize()
110+
modifier = Modifier
111+
.matchParentSize()
112+
.graphicsLayer {
113+
translationY = midOffset
114+
}
77115
)
78116

79117
Image(
@@ -97,4 +135,6 @@ class MainActivity : ComponentActivity() {
97135
}
98136
}
99137
}
138+
139+
private fun Float.toDp() = (this / Resources.getSystem().displayMetrics.density).dp
100140
}

0 commit comments

Comments
 (0)