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

Nicolai

03/24/2024, 7:26 PM
Hey! 👋 I hope one of you can help me. I’ve been trying to create a DraggableContainer composable that I use in a LazyColumn. This works but as you can see I want to dynamically change the endPosition so the content composable can be swiped enough away to show the full width of the offscreenContent. Right now that doesn’t work. The DragAnchors.End at endPosition doesn’t seem to get updated and hence the offScreenContent is not fully visible. Code in thread 🧵
Copy code
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun DraggableContainer(
    content: @Composable () -> Unit = {},
    offScreenContent: @Composable RowScope.() -> Unit = {}
) {
    var endPosition by remember {
        mutableFloatStateOf(-500f)
    }
    val density = LocalDensity.current
    val state = remember {
        AnchoredDraggableState(
            initialValue = DragAnchors.Start,
            positionalThreshold = { distance: Float -> distance * 0.5f },
            velocityThreshold = { with(density) { 100.dp.toPx() } },
            animationSpec = tween(),
        ).apply {
            updateAnchors(
                DraggableAnchors {
                    DragAnchors.Start at 0f
                    DragAnchors.End at endPosition
                }
            )
        }
    }
    Box(modifier = Modifier
        .offset {
            IntOffset(
                x = state
                    .requireOffset()
                    .roundToInt(),
                y = 0,
            )
        }
        .anchoredDraggable(state, Orientation.Horizontal)) {

        Layout(
            modifier = Modifier
                .fillMaxWidth()
                .wrapContentHeight(),
            content = {
                content()
                Row(modifier = Modifier.padding(horizontal = 16.dp)) {
                    offScreenContent()
                }

            },
            measurePolicy = { measurables, constraints ->
                val placeables = measurables.mapIndexed { index, measurable ->
                    if (index == 0) {
                        measurable.measure(constraints)
                    } else {
                       val offScreenPlaceable = measurable.measure(Constraints())
                        endPosition = -offScreenPlaceable.width.toFloat()
                        offScreenPlaceable
                    }
                }

                val height = placeables.maxOf { it.height }
                layout(constraints.maxWidth, height) {
                    placeables.forEachIndexed { index, placeable ->
                        if (index == 0) {
                            placeable.place(0, 0)
                        } else {
                            placeable.place(
                                constraints.maxWidth + 16.dp.roundToPx(),
                                height / 2 - placeable.height / 2
                            )
                        }
                    }
                }
            }
        )
    }
}
Found the solution to have my state remember(endPosition) 👍