Last active
June 30, 2020 14:39
-
-
Save odecaux/808c71b646c0a170cfeb2cb0686858e0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun HorizontalSliderWithAnchor( | |
modifier : Modifier = Modifier, | |
children: @Composable() () -> Unit | |
) { | |
var childPositions by state { listOf<ChildPosition>()} | |
WithConstraints() { | |
val boxWidth = with(DensityAmbient.current) { constraints.maxWidth.toDp() } | |
//setting up all the anchors. | |
//if childPositions is empty (first pass), anchors are empty, and the scroll range is 0f->0f | |
val leftBoundPx : Px = -(childPositions.lastOrNull()?.left?.toPx() ?: 0.px) | |
val rightBoundPx = 0.px | |
val flingConfig = AnchorsFlingConfig( childPositions.map { -it.left.toPx().value} ) | |
val scrollPosition = animatedFloat(0f) | |
scrollPosition.setBounds(leftBoundPx.value, rightBoundPx.value) | |
val xOffset = with(DensityAmbient.current) { scrollPosition.value.toDp() } | |
Surface(modifier = modifier | |
.draggable( | |
startDragImmediately = scrollPosition.isRunning, | |
dragDirection = DragDirection.Horizontal, | |
onDragStopped = { scrollPosition.fling(flingConfig, it) }) | |
{ delta -> | |
scrollPosition.snapTo(scrollPosition.value + delta) | |
delta | |
} | |
.width(boxWidth) | |
) { | |
Layout(children, modifier | |
.clipToBounds() | |
.offset(x = xOffset)) { measurables, constraints, _ -> | |
//unsure what I'm doing here, seems to allow children to use .fillMaxWidth() | |
val childConstraints = constraints.copy(minWidth = IntPx.Zero) | |
val newTabPositions = mutableListOf<ChildPosition>() | |
var fixedSpace = IntPx.Zero | |
var crossAxisSpace = IntPx.Zero | |
//measuring and storing the positions | |
val placeables = measurables.map{child -> | |
val placeable = child.measure(childConstraints) | |
newTabPositions.add(ChildPosition( | |
left = fixedSpace, | |
width = placeable.width)) | |
fixedSpace += placeable.width | |
crossAxisSpace = max(crossAxisSpace, placeable.height) | |
placeable | |
} | |
//transfering positions, recomposing ? | |
if (childPositions != newTabPositions) { | |
childPositions = newTabPositions | |
} | |
val width = min(fixedSpace, constraints.maxWidth) | |
val height = min(crossAxisSpace, constraints.maxHeight) | |
//placing as a limitless row | |
layout(width , height) { | |
var position = 0.ipx | |
placeables.forEach { | |
it.place(position, 0.ipx) | |
position += it.width | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment