(Jetpack Compose) Как правильно посчитать значение паралакса?

Я делаю вью с паралакс эффектом и чтоб когда юзер скролит вниз, появлялся actionbar так же как описано в этой статье

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

Делаю это вот так

@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
                )
            )
        }
    }
}

И вроде бы все работает, но проблема в том, что значения насколько быстро будет уезжать паралакс и насколько быстро будет появляться actionbar зависит от высоты контента.

Как видно в примере вот тут я под изображение добавляю 100 текстов

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

и все работает, но если 100 поменять на 1000, то паралакс медленнее реагирует и что самое главное для того, чтоб появился actionbar нужно пролистать пол списка вниз

Как это сделать, чтоб правильно работало? Нужно, чтоб отклик паралакса и отображение actionbar не зависило от высоты контента, хоть это 100 текстов хоть 1000 должно работать одинаково


Ответы (1 шт):

Автор решения: vitidev

(scrollState.value.toFloat() / scrollState.maxValue) * 5f высчитывает прозрачность в зависимости от позиции скрола. Но почему то при этом завязано на общую высоту. Общая высота scrollState.maxValue разная, а потому и результат выражения разный.

А значит чтобы всегда было фиксированное значение нужно зависеть только от scrollState.value, а остальные значения должны быть константами.

Что-то вида scrollState.value.toFloat() / 5000) * 5f

ps: Вместо константы в общем случае правильнее завязываться на высоту картинки, чтобы к моменту ухода картинки была полная непрозрачность, и от него получить нужное число для деления.

→ Ссылка