Compose Drag Drop(在组件之间传递数据)-从下到上滚动时,可拖动项目状态不会改变

问题描述 投票:0回答:1

我正在使用 Jetpack Compose 实现拖放功能。它已经能够将数据从一个地方拖放到另一个地方,并在可拖动项目遇到上下边缘时自动滚动。

现在我尝试添加拖动时可拖动项目状态的更改 - 一般内容(已启动)、已启用的放置目标(已启用)和已禁用的放置目标(已禁用)。向下拖动时它工作得很好,但向上拖动时它保持默认 - 启动状态。我需要帮助来解决这个问题并尽快修复。

外观如何:

完整代码位于

draggable-item
分支 -> github 存储库

我可以查明问题根源,但无法找到发生这种情况的原因 - 无论是我使用错误还是

onGloballyPositioned/boundsInRoot/contains
API 有错误。

var isItemInDropTarget by remember { mutableStateOf(false) }
var wasInTarget by remember { mutableStateOf(true) }

Box(
    modifier = modifier
        .onGloballyPositioned {
            it.boundsInRoot().let { rect ->
                isItemInDropTarget = (rect.contains(dragPosition) && state.isDragging)
                    .also { inDropTarget ->
                        if (inDropTarget != wasInTarget) {
                            Log.d(Tag, "isItemInDropTarget changed: $wasInTarget >>> $inDropTarget")
                            wasInTarget = inDropTarget
                        }
                    }
            }
        },
)

Rect.contains()
不知何故被触发了两次,然后定义了可拖动项目状态(在
LaunchedEffect
中,但在这里并不重要)。

//Drag started - true - as drag source is also a drop target and item is in bounds
D  isItemInDropTarget changed: false >>> true

// Hover over next target down 
D  isItemInDropTarget changed: true >>> false
D  isItemInDropTarget changed: false >>> true
// Hover over next target down
D  isItemInDropTarget changed: true >>> false
D  isItemInDropTarget changed: false >>> true

// Hover over next target up - notice reverse order
D  isItemInDropTarget changed: false >>> true
D  isItemInDropTarget changed: true >>> false
// Hover over next target up
D  isItemInDropTarget changed: false >>> true
D  isItemInDropTarget changed: true >>> false

我还应该提到,当目标之间没有足够的空间时,就会出现这个问题。因此,如果要在最后一个目标下拖动并返回到该目标,或者在两个之间有更多空间的目标之间向上拖动,它将被正确着色,但旁边的目标不会。

android kotlin drag-and-drop android-jetpack-compose
1个回答
0
投票

感谢Phil Dukhov的评论。我一开始并没有明白,但在与同事检查我的代码后,我们提出了一个解决方案。它并不完美,但它有效。

因此,由于在离开和进入两个目标时触发 Rect.contains(),我们添加了活动目标的地图及其 ID 和正确的状态。项目在悬停时添加,在离开时删除。当地图有一个项目时获得最终状态,因此它应该是

Enabled
Disabled
或者默认为
Initiated

private val draggableItemState: DraggableItemState
    get() {
        return if (activeTargetItems.size == 1) {
            activeTargetItems[activeTargetItems.keys.first()]!!
        } else {
            DraggableItemState.Initiated
        }
    }

private var activeTargetItems by mutableStateOf(emptyMap<String, DraggableItemState>())

fun onHoveredTarget(id: String, enabled: Boolean) {
    val draggableItemState = if (enabled) DraggableItemState.Enabled else DraggableItemState.Disabled
    activeTargetItems += (id to draggableItemState)
}

fun onUnHoveredTarget(id: String) {
    activeTargetItems = activeTargetItems.toMutableMap().also { it.remove(id) }
}
© www.soinside.com 2019 - 2024. All rights reserved.