I'm trying to develop a drag and drop feature for a grid system with Jetpack Compose.
The user will have the ability to long press on a UI component and drag it to another location within a grid system. Once the selected UI component is partially within the bounds of a grid square, that UI component will automatically snap into the center of that grid square when the user lifts there finger.
I have developed the first half successfully. The user long presses on a UI component and can drag it. The second half is what doesn't work. The UI component won't snap into place when it's within the bounds of a grid square.
In the sample project I have two boxes. One is moveable and the other is static, it represents the grid square. I'm using a pointerInput
modifier and a detectDragGesturesAfterLongPress
function to allow for dragging. I'm using the onGloballyPositioned
modifier to obtain the coordinates of the static box / grid square. Then I check to see if the static box contains the offset coordinates of the movable box. If it does then the coordinates of the movable box will be set to the coordinates of the static box. However this doesn't work.
Here is the code
// Coordinates Of Moveable Box
var x by remember { mutableStateOf(0) }
var y by remember { mutableStateOf(0) }
// Coordinates Of Static Box
var staticBoxCoordinates by remember { mutableStateOf(Rect.Zero) }
// Layout
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceEvenly
) {
// Moveable Box
Box(
modifier = Modifier
.offset(x = x.dp, y = y.dp)
.zIndex(2f)
.background(Color.LightGray)
.pointerInput(Unit) {
detectDragGesturesAfterLongPress (
// On Drag
onDrag = { change, dragAmount ->
x += (dragAmount.x.toInt() / 3)
y += (dragAmount.y.toInt() / 3)
change.consume()
},
// On Drag End
onDragEnd = {
// Check If Moveable Box Is Inside Static Box
if (staticBoxCoordinates.contains(Offset(x.toFloat(), y.toFloat()))) {
x = staticBoxCoordinates.topLeft.x.toInt()
y = staticBoxCoordinates.topLeft.y.toInt()
}
}
)
}
.size(150.dp)
)
// Static Box
Box(
modifier = Modifier
.onGloballyPositioned { staticBoxCoordinates = it.boundsInRoot() }
.zIndex(1f)
.background(Color.DarkGray)
.size(150.dp)
)
}