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

pavankumar

02/14/2022, 8:24 AM
Hi all, I trying to create a snappable widget where any user can drag a widget within its parent bounds and when user lifts his/her finger then child widget should snap to nearest corner (like to one of top-left, top-right, bottom-left, bottom-right). i wrote below code but it didn't quite achieved the goal. Help is needed to understand where i'm doing wrong. help is much appreciated.
Copy code
Code snipper in the thread.
🧵 2
c

Colton Idle

02/14/2022, 12:03 PM
@pavankumar Could you edit your question to put more of it in the thread? See: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1616265877303000
p

pavankumar

02/14/2022, 12:05 PM
Please find the code snipper here.
Copy code
BoxWithConstraints(Modifier.fillMaxSize()) {
        val offset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }
        val width = constraints.maxWidth.toFloat()
        val height = constraints.maxHeight.toFloat()

        Box(
            Modifier
                .offset { IntOffset(offset.value.x.roundToInt(), offset.value.y.roundToInt()) }
                .background(Color.Blue)
                .size(50.dp)
                .pointerInput(Unit) {
                    val decay = SplineBasedFloatDecayAnimationSpec(this)
                    coroutineScope {
                        val tracker = VelocityTracker()
                        detectDragGestures(onDragEnd = {
                            val velocity = Offset(tracker.calculateVelocity().x, tracker.calculateVelocity().y)
                            val targetX = decay.getTargetValue(offset.value.x, velocity.x)
                            val targetY = decay.getTargetValue(offset.value.y, velocity.y)

                            val calculatedX = if (targetX.absoluteValue  < (width - targetX.absoluteValue).absoluteValue) {
                                0f
                            } else {
                                width
                            }

                            val calculatedY = if (targetY.absoluteValue  < (height - targetY.absoluteValue).absoluteValue) {
                                0f
                            } else {
                                height
                            }
                            offset.updateBounds(
                                Offset(0f, 0f),
                                Offset(width - size.width, height - size.height.toFloat())
                            )
                            launch {
                                offset.animateTo(Offset(calculatedX, calculatedY), SpringSpec<Offset>(), velocity)
                            }
                        }, onDrag = { change, dragAmount ->
                            change.consumeAllChanges()
                            tracker.addPosition(change.uptimeMillis, change.position)
                            launch {
                                offset.snapTo(
                                    Offset(
                                        offset.value.x + dragAmount.x,
                                        offset.value.y + dragAmount.y
                                    )
                                )
                            }
                        })
                    }
                }
        )
    }
👍 1
@Colton Idle done. thanks for letting me know
👍 1
7 Views