I have a collection of five items, all of which are draggable. I want to achieve behavior in which the dragged item will overlap all the others. I tried changing the zIndex parameter but it didn't work, what am I doing wrong?
item code:
@Composable
fun <T> DragTarget(
dataToDrop: T,
content: @Composable () -> Unit) {
var dragOffset by remember { mutableStateOf(Offset.Zero) }
var currentPosition by remember { mutableStateOf(Rect.Zero) }
val currentState = LocalDragTargetInfo.current
Box(
modifier = Modifier
.zIndex(if (currentState.isDragging) 5f else 0f) // my first try
.offset {
IntOffset(
dragOffset.x.roundToInt(),
dragOffset.y.roundToInt()
)
}
.onGloballyPositioned { layout ->
layout
.boundsInWindow()
.let { rect ->
currentPosition = rect
}
}
.pointerInput(dataToDrop) {
detectDragGestures(
onDragStart = {
currentState.isDragging = true
currentState.dataToDrop = dataToDrop
currentState.dragPosition = currentPosition
},
onDrag = { change, dragAmount ->
change.consume()
dragOffset += dragAmount
currentState.dragPosition = currentPosition
},
onDragEnd = {
currentState.isDragging = false
dragOffset = Offset.Zero
currentState.dragPosition = Rect.Zero
}
)
},
contentAlignment = Alignment.Center
) {
content()
}}
item collection code
@Composable
fun TestView() {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.spacedBy(16.dp, alignment = Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically
) {
DragTarget(dataToDrop = null) {
Box(modifier = Modifier.zIndex(5f) // my second try
.size(50.dp).background(Color.Blue))
}
DragTarget(dataToDrop = null) {
Box(modifier = Modifier.size(50.dp).background(Color.Green))
}
DragTarget(dataToDrop = null) {
Box(modifier = Modifier.size(50.dp).background(Color.LightGray))
}
DragTarget(dataToDrop = null) {
Box(modifier = Modifier.size(50.dp).background(Color.Yellow))
}
DragTarget(dataToDrop = null) {
Box(modifier = Modifier.size(50.dp).background(Color.Red))
}
}}
and my DragTargetInfo:
class DragTargetInfo {
var isDragging by mutableStateOf(false)
var dragPosition by mutableStateOf(Rect.Zero)
var dataToDrop by mutableStateOf<Any?>(null)}
val LocalDragTargetInfo = compositionLocalOf { DragTargetInfo() }
I will be grateful for any tips as I have been trying to untangle this tangle for several days now and achieve the desired result. Peace to all friends)
One solution is moving zIndex
into a state variable and making it independent of the currentState.isDragging
and changing its value directly on onDragStart
and onDragEnd
lambdas.
@Composable
fun <T> DragTarget(
dataToDrop: T,
content: @Composable BoxScope.() -> Unit
) {
var dragOffset by remember { mutableStateOf(Offset.Zero) }
var currentPosition by remember { mutableStateOf(Rect.Zero) }
val currentState = LocalDragTargetInfo.current
var zIndex by remember { mutableFloatStateOf(0f) }
Box(
modifier = Modifier
.zIndex(zIndex)
.offset {
IntOffset(
dragOffset.x.roundToInt(),
dragOffset.y.roundToInt()
)
}
.onGloballyPositioned { layout ->
layout
.boundsInWindow()
.let { rect ->
currentPosition = rect
}
}
.pointerInput(dataToDrop) {
detectDragGestures(
onDragStart = {
currentState.isDragging = true
currentState.dataToDrop = dataToDrop
currentState.dragPosition = currentPosition
zIndex = 1f
},
onDrag = { change, dragAmount ->
change.consume()
dragOffset += dragAmount
currentState.dragPosition = currentPosition
},
onDragEnd = {
currentState.isDragging = false
dragOffset = Offset.Zero
currentState.dragPosition = Rect.Zero
zIndex = 0f
}
)
},
contentAlignment = Alignment.Center,
content = content
)
}
@Composable
fun TestView() {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.spacedBy(
16.dp,
alignment = Alignment.CenterHorizontally
),
verticalAlignment = Alignment.CenterVertically
) {
DragTarget(dataToDrop = "Blue") {
Box(
modifier = Modifier
.size(50.dp)
.background(Color.Blue)
)
}
DragTarget(dataToDrop = "Green") {
Box(
modifier = Modifier
.size(50.dp)
.background(Color.Green)
)
}
DragTarget(dataToDrop = "Gray") {
Box(
modifier = Modifier
.size(50.dp)
.background(Color.LightGray)
)
}
DragTarget(dataToDrop = "Yellow") {
Box(
modifier = Modifier
.size(50.dp)
.background(Color.Yellow)
)
}
DragTarget(dataToDrop = "Red") {
Box(
modifier = Modifier
.size(50.dp)
.background(Color.Red)
)
}
}
}