Apple Stock Bottom Sheet Animation

This component demonstrate how we can create the animation in the apple stock app when the bottom sh...…

Next Component
package com.example.ui.components

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.*
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

/**
 * Entry point for the [VerticalColorList] component.
 */
@Composable
fun ColorListPreview() {
    VerticalColorList()
}

/**
 * A vertical list with scroll animation.
 */
@OptIn(ExperimentalStdlibApi::class)
@Composable
fun VerticalColorList() {
    val colorData = (0..24).map {
        Color(255 - (it * 2), 183 + (it * 2), 94 + (it * 2))
    }
    val scrollPosition = rememberLazyListState()

    VerticalScrollContainer(
        state = scrollPosition,
        modifier = Modifier.fillMaxSize()
    ) {
        ItemScrollContainer(
            colorData = colorData,
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 16.dp, vertical = 6.dp)
        )
    }
}

@Composable
fun ItemScrollContainer(
    colorData: List<Color>,
    modifier: Modifier
) {
    items(
        colorData.size,
        key = { colorData[it].hashCode() }
    ) { index ->
        var itemHeight by remember { mutableStateOf(0) }
        HorizontalContainer(
            contentAlignment = Alignment.BottomEnd,
            modifier = modifier
                .onSizeChanged {
                    itemHeight = it.height
                }
                .graphicsLayer {
                    clip = true
                    shape = RoundedCornerShape(12.dp)
                    if (index == scrollPosition.firstVisibleItemIndex) {
                        val scrollOffsetRatio = scrollPosition.firstVisibleItemScrollOffset.toFloat() / itemHeight
                        val scaleFactor = 1f - scrollOffsetRatio * .3f
                        scaleY = scaleFactor
                        scaleX = scaleFactor
                        alpha = 1f - scrollOffsetRatio
                        transformOrigin = TransformOrigin(
                            pivotFractionX = .5f,
                            pivotFractionY = 1f
                        )
                    }
                }
                .background(colorData[index])
        ) {
            Text(
                text = "#${colorData[index].toArgb().toHexString().drop(2).uppercase()}",
                color = Color.White,
                style = TextStyle(
                    fontWeight = FontWeight.Bold,
                    fontSize = 18.sp
                ),
                modifier = Modifier.padding(16.dp, 64.dp, 16.dp, 16.dp)
            )
        }
    }
}