Nicolai
03/24/2024, 7:26 PMNicolai
03/24/2024, 7:26 PM@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
)
}
}
}
}
)
}
}
Nicolai
03/24/2024, 7:50 PM