2

I am testing out the solution provided by Asperi here:

SwiftUI | Using onDrag and onDrop to reorder Items within one single LazyGrid?

so,

what I would like to do is to add a contextMenu on a cell, and if the user chooses to reorder cells, then would enable the onDrag and onDrop gestures.

I looked into the simultaneousGesture but, I am not sure how trigger the contextMenu while the view also has onDrag attached to it.

so I tried something like this:

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

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)

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

So, the contextMenu never triggers unless I remove the onDrag and onDrop gestures first.

Is there a way to use the contextMenu to "enter" an edit mode to allow drag and drop? Is there a way to make it work while the onDrag and onDrop gestures are installed on the view?

Asperi is right. For the curious as to how I got around doing this I used this conditional View extension:

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
        }
    }
}
0

1 Answer 1

2

The both use same gesture (LongPress) for activation, so there is direct conflict. A possible approach is to make onDrag conditional (toggled by some external command).

The Draggable/canDrag can be similar as Droppable/acceptDrop in https://stackoverflow.com/a/61081772/12299030.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.