SwiftUI:允许在视图中使用“onDrag”同时进行手势吗?

SwiftUI: allow simultaneous gestures with `onDrag` in view?

我正在这里测试 Asperi 提供的解决方案:

所以,

我想做的是在单元格上添加一个 contextMenu,如果用户选择重新排序单元格,那么将启用 onDrag 和 onDrop 手势。

我查看了 simultaneousGesture 但是,我不确定如何在视图还附加了 onDrag 时触发 contextMenu。

所以我尝试了这样的事情:

...............

ScrollView(.vertical, showsIndicators: true) {
    LazyVGrid(columns: gridItems, spacing: 0) {
        ForEach(model.data) { d in
            GridItemView(d: d)
                .frame(width: side, height: side)
                .overlay(dragging?.id == d.id ? Color.white.opacity(0.8) : Color.clear)
                .contextMenu {
                    Button {
                        editCells.toggle()
                    } label: {
                        Label("Edit...", systemImage: "pencil")
                    }

                    // other options .....
                }
                .onDrag {
                    self.dragging = d
                    return NSItemProvider(object: String(d.id) as NSString)
                }
                .disabled(!editCells)
                .onDrop(of: [UTType.text], delegate: DragRelocateDelegate(item: d, listData: $model.data, current: $dragging))
                            .disabled(!editCells)
           }
        }
       .animation(.default, value: model.data)

...............

因此,contextMenu 永远不会触发,除非我先删除 onDrag 和 onDrop 手势。

有没有办法使用上下文菜单“进入”编辑模式以允许拖放?有没有办法在视图上安装 onDrag 和 onDrop 手势时让它工作?

Asperi 是对的。为了好奇我是如何做到这一点的,我使用了这个条件视图扩展:

extension View {
    /// Applies the given transform if the given condition evaluates to `true`.
    /// - Parameters:
    ///   - condition: The condition to evaluate.
    ///   - transform: The transform to apply to the source `View`.
    /// - Returns: Either the original `View` or the modified `View` if the condition is `true`.
    @ViewBuilder func `if`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
        if condition {
            transform(self)
        } else {
            self
        }
    }
}

两者使用相同的手势(长按)激活,因此存在直接冲突。一种可能的方法是使 onDrag 有条件(由一些外部命令切换)。

Draggable/canDrag 可以类似于 中的 Droppable/acceptDrop