1

I need to do a parallax implementation and in addition when user is scrolling down actionbar should appear. I am following this tutorial:

https://proandroiddev.com/parallax-in-jetpack-compose-bf521244f49

There is an implementation:

@Composable
fun HeaderBarParallaxScroll() {
    val scrollState = rememberScrollState()
    Box {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .verticalScroll(scrollState),
        ) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(500.dp)
                    .background(Color.White)
                    .graphicsLayer {
                        Log.e(
                            "scroll",
                            "${scrollState.value.toFloat()}, max = ${scrollState.maxValue}, ratio = ${(scrollState.value.toFloat() / scrollState.maxValue)}"
                        )
                        alpha = 1f - ((scrollState.value.toFloat() / scrollState.maxValue) * 1.5f)
                        translationY = 0.5f * scrollState.value
                    },
                contentAlignment = Alignment.Center
            ) {
                Image(
                    painterResource(id = R.drawable.ic_launcher_foreground),
                    contentDescription = "tiger parallax",
                    contentScale = ContentScale.Crop,
                    modifier = Modifier.fillMaxSize()
                )
            }

            repeat(100) {
                Text(
                    text = "MyText",
                    modifier = Modifier.background(
                        Color.White
                    ),
                    style = TextStyle(
                        color = Color.Red,
                        fontSize = 24.sp
                    )
                )
            }
        }

        Box(
            modifier = Modifier
                .alpha(min(1f, (scrollState.value.toFloat() / scrollState.maxValue) * 5f))
                .fillMaxWidth()
                .height(60.dp)
                .background(Color.Yellow),
            contentAlignment = Alignment.CenterStart
        ) {
            Text(
                text = "Header bar",
                modifier = Modifier.padding(horizontal = 16.dp),
                style = TextStyle(
                    fontSize = 24.sp,
                    fontWeight = FontWeight.W900,
                    color = Color.Black
                )
            )
        }
    }
}

Looks like everything is working as expected, however, if I change the value repeat in this block

repeat(100) {
                Text(
                    text = "MyText",
                    modifier = Modifier.background(
                        Color.White
                    ),
                    style = TextStyle(
                        color = Color.Red,
                        fontSize = 24.sp
                    )
                )
            }

instead of 100 -> 1000 parallax working slower and in order for the actionbar to appear I need to scroll like half of the list, so to put it differently parallax responsiveness depends on how many items (height) are in the content. Eg: if it is 100 it works as expected, however, if it is 1000 it works much slower...

How to make it work properly?

Sirop4ik
  • 4,543
  • 2
  • 54
  • 121

1 Answers1

2

Don't calculate the ratio based on the scroll.maxValue, but use the screen height as the max bound. Get it in pixels like this.

val screenHeight = with (LocalDensity.current) { LocalConfiguration.current.screenHeightDp.dp.roundToPx() }

These are all composables, so you'll need to call this logic within a Composable scope. After the initialization, of course, the variable can be used anywhere, even in non-composable scopes.

Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42