https://kotlinlang.org logo
#compose
Title
# compose
a

Andrei Kovalev

10/08/2021, 9:01 AM
Hi folks, I’m trying to resolve the issue when cards overlap in grid view with
zIndex
, but the problem is that in lazy LazyGrid Implementation
Copy code
val rows = (scope.totalSize + nColumns - 1) / nColumns
    LazyColumn(
        modifier = modifier,
        state = state,
        contentPadding = contentPadding
    ) {
        items(rows) { rowIndex ->
            Row {
                for (columnIndex in 0 until nColumns) {
                    val itemIndex = rowIndex * nColumns + columnIndex
                    if (itemIndex < scope.totalSize) {
                        Box(
                            modifier = Modifier.weight(1f, fill = true),
                            propagateMinConstraints = true
                        ) {
                            scope.contentFor(itemIndex, this@items).invoke()
                        }
                    } else {
                        Spacer(Modifier.weight(1f, fill = true))
                    }
                }
            }
        }
    }
our composable items are wrapped in a Box, but
zIndex
only works for direct children of the composable node. How would you resolve this issue? Any suggestions are welcome
1
came up with custom lazy grid implementation and providing values to the parent Box via local composition
p

patrick

10/08/2021, 9:52 AM
Sounds interesting! Do you mind sharing it here for other people to find should the question come up again?
a

Andrei Kovalev

10/08/2021, 11:12 AM
yeah, sure
Copy code
LazyColumn(
        modifier = modifier,
        state = state,
        contentPadding = contentPadding
    ) {
        items(rows) { rowIndex ->
            CompositionLocalProvider(
                LocalSwipableIndex provides mutableStateOf(-1),
            ) {
                Row {
                    for (columnIndex in 0 until nColumns) {
                        val itemIndex = rowIndex * nColumns + columnIndex
                        if (itemIndex < scope.totalSize) {
                            Box(
                                modifier = Modifier
                                    .weight(1f, fill = true)
                                    .zIndex(if (itemIndex == LocalSwipableIndex.current.value) 1f else 0f),
                                propagateMinConstraints = true
                            ) {
                                scope.contentFor(itemIndex, this@items).invoke()
                            }
                        } else {
                            Spacer(Modifier.weight(1f, fill = true))
                        }
                    }
                }
            }
        }
    }
So I provide state of the swipeable card for each row and in my SwipabeCard I set current index of the card which is being swiped:
Copy code
@Composable
fun SwipableProfileCard(
    index: Int,
    model : ProfileCardModel
) {
    if (swipeState.swipeProgress.value.absoluteValue > 0) {
        LocalSwipableIndex.current.value = index
    }
}
this is what I was trying to solve
a

Andrey Kulikov

10/11/2021, 12:08 PM
It is not yet done, but the plan is to introduce a more low level api LazyLayout where you can provide different layout managers, similarly to how it works in RecyclerView, and after that LazyGrid will be reimplemented without adding extra Box for the item to support use cases like this
a

Andrei Kovalev

10/11/2021, 12:10 PM
thanks for the update, @Andrey Kulikov
a

Alex

12/08/2021, 3:57 PM
Hey @Andrey Kulikov, is this already done? Or is there any update on this? 🙂
a

Andrei Kovalev

12/08/2021, 3:58 PM
I’ve seen 1.1.0 beta LazyGrid is re-implemented, but I haven’t tried it yet
a

Andrey Kulikov

12/08/2021, 5:54 PM
it is still in progress
🙏 1
3 Views