You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中Row内拖拽项无法置顶问题排查

问题原因分析
  • 全局共享状态导致层级无差异:你的LocalDragTargetInfo使用了全局的isDragging状态,任何一个DragTarget触发拖拽时,所有同级DragTarget都会检测到isDragging = true,全部将自身zIndex设为5f,层级完全相同,自然无法实现拖拽项覆盖其他项的效果。
  • zIndex作用范围限制:zIndex仅对同一父容器内的同级元素生效,必须确保只有当前拖拽的DragTarget拥有更高层级值。
解决方案

1. 修改DragTargetInfo,记录精准拖拽标识

将全局isDragging改为记录当前拖拽的数据实例,实现精准区分:

class DragTargetInfo {
    var draggedData: Any? by mutableStateOf(null)
    var dragPosition by mutableStateOf(Rect.Zero)
}

val LocalDragTargetInfo = compositionLocalOf { DragTargetInfo() }

2. 更新DragTarget组件,精准判断拖拽项

调整zIndex判断逻辑,仅当前拖拽项设置更高层级:

@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.draggedData === dataToDrop) 5f else 0f)
            .offset {
                IntOffset(
                    dragOffset.x.roundToInt(),
                    dragOffset.y.roundToInt()
                )
            }
            .onGloballyPositioned { layout ->
                currentPosition = layout.boundsInWindow()
            }
            .pointerInput(dataToDrop) {
                detectDragGestures(
                    onDragStart = {
                        currentState.draggedData = dataToDrop
                        currentState.dragPosition = currentPosition
                    },
                    onDrag = { change, dragAmount ->
                        change.consume()
                        dragOffset += dragAmount
                        currentState.dragPosition = currentPosition
                    },
                    onDragEnd = {
                        currentState.draggedData = null
                        dragOffset = Offset.Zero
                        currentState.dragPosition = Rect.Zero
                    }
                )
            },
        contentAlignment = Alignment.Center
    ) {
        content()
    }
}

3. 调整TestView的使用方式

给每个DragTarget传入唯一的dataToDrop值(不能传null,否则无法区分):

@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))
        }
    }
}

额外优化建议

如果层级问题仍存在,可尝试用graphicsLayer替代zIndex修饰符,兼容性更好:

.graphicsLayer {
    zIndex = if (currentState.draggedData === dataToDrop) 5f else 0f
}

内容的提问来源于stack exchange,提问作者Alex Bro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:05:15