Creating Overlapping Effect in Jetpack Compose LazyColumn: Middle Item Above Others

92 Views Asked by At

Compose enthusiasts! I'm currently exploring the possibilities of Jetpack Compose and trying to implement a visually appealing layout within a LazyColumn. Specifically, I'm aiming to create an overlapping effect among the items, where the middle item is positioned on top of the others.

In my attempts, I've experimented with the spacedBy parameter using a negative value (e.g., -50.dp), successfully achieving the overlap. However, I'm encountering a challenge: while the middle item overlaps the items above it, it remains beneath the items below it. My goal is to have the middle item on top of all others.

Below are snippets of my two attempts:

Using ScalingLazyColumn from compose wear:

val values = remember { radioList }
        val scalingLazyListState = rememberScalingLazyListState()

        val isScrollingFast by remember { mutableStateOf(false) }

        ScalingLazyColumn(
            state = scalingLazyListState,
            verticalArrangement = Arrangement.spacedBy(
                space = (-50).dp,
                alignment = Alignment.CenterVertically
            ),
            modifier = Modifier.wrapContentSize(),
            autoCentering = AutoCenteringParams(
                itemIndex = if (isScrollingFast) scalingLazyListState.centerItemIndex else 0,
                itemOffset = 0,
            ),
            scalingParams = ScalingLazyColumnDefaults.scalingParams(
                edgeScale = 0.3f,
                edgeAlpha = 1f,
                minElementHeight = 0.1f,
                maxElementHeight = 0.9f,
                minTransitionArea = 0.5f,
                maxTransitionArea = 0.5f,
                scaleInterpolator = LinearOutSlowInEasing,
                viewportVerticalOffsetResolver = { (it.maxHeight / 10f).toInt() }
            ),
        ) {
            itemsIndexed(values) { index, item ->
                CoilImage(
                    component = rememberImageComponent {
                        if (item.isSelected) {
                            +BlurTransformationPlugin(radius = 5)
                        }
                    },
                    modifier = Modifier
                        .size(250.dp),
                    imageModel = { item.imageUrl },
                )
            }
        }

Using LazyRow:

val listState = rememberLazyListState()
        val horizontalContentPadding = 0.dp
        val boxSize = 250.dp
        BoxWithConstraints {
            val halfRowWidth = constraints.maxWidth / 2
            LazyRow(
                state = listState,
                horizontalArrangement = Arrangement.spacedBy((-120).dp),
                contentPadding = PaddingValues(horizontal = horizontalContentPadding, vertical = 8.dp),
                modifier = Modifier
                    .fillMaxWidth()
            ) {
                itemsIndexed(radioList) { i, item ->
                    val opacity by remember {
                        derivedStateOf {
                            val currentItemInfo = listState.layoutInfo.visibleItemsInfo
                                .firstOrNull { it.index == i }
                                ?: return@derivedStateOf 20f
                            val itemHalfSize = currentItemInfo.size / 2
                            (1f - minOf(1f, abs(currentItemInfo.offset + itemHalfSize - halfRowWidth).toFloat() / halfRowWidth) * 0.5f)
                        }
                    }
                    Box(
                        contentAlignment = Alignment.Center,
                        modifier = Modifier
                            .scale(opacity)
                            .alpha(opacity)
                            .size(boxSize)
                            .background(Color.Blue)
                    ) {
                        AsyncImage(
                            contentScale = ContentScale.Crop,
                            modifier = Modifier
                                .size(250.dp),
                            model = radioList[i].imageUrl,
                            contentDescription = null
                        )
                    }
                }
            }
        }

I've marked the areas where the images overlap with red lines. From these red lines onwards, I'd like the items at the edges to be hidden, so they don't interfere with the overlapping effect.

image1 image2

What did you try? I attempted to create an overlapping effect among items within ScalingLazyColumn and LazyRow using negative values with the spacedBy parameter.

What were you expecting to happen? I expected the middle item to overlap the items above it and be consistently on top of all others, creating a visually appealing layout.

What actually resulted? While the middle item successfully overlapped the items above it, it remained beneath the items below it, leading to the current challenge.

0

There are 0 best solutions below