11package xyz.teamgravity.multilayerparallaxscrolleffect
22
3+ import android.content.res.Resources
34import android.os.Bundle
45import androidx.activity.ComponentActivity
56import androidx.activity.compose.setContent
@@ -16,8 +17,13 @@ import androidx.compose.runtime.setValue
1617import androidx.compose.ui.Alignment
1718import androidx.compose.ui.Modifier
1819import androidx.compose.ui.draw.clipToBounds
20+ import androidx.compose.ui.geometry.Offset
1921import androidx.compose.ui.graphics.Brush
2022import 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
2127import androidx.compose.ui.layout.ContentScale
2228import androidx.compose.ui.platform.LocalConfiguration
2329import 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