I'm using .contextMenu together with .onDrag on a view and this seems to be very tricky:
The background color changes to gray by setting dragging to true. This is triggered by .onDrag which already happens when opening the context menu (a bit early but ok). When I use the button to close the menu I can set dragging to false. When I use the drag, the dragging state is changed back to false when the ItemProvider is deinitialized. So far so good.
The problem
When I tap outside the context menu to dismiss it, I seem to have no way to set the dragging state back to false. Adding .onDisappear to the Button in the menu does not work.
What am I doing wrong here? Any way I can get either get notified when the context menu closes or have the state change of dragging happen when the drag actually begins (so that the background is not immediately gray when the context menu is opened)?
Code below video.
struct ContentView: View {
@State var dragging = false
var body: some View {
ZStack {
Rectangle()
.foregroundColor(.blue)
.frame(width: 100, height: 100)
.onDrag {
dragging = true
let provider = ItemProvider(contentsOf: URL(string: "Test")!)!
provider.didEnd = {
DispatchQueue.main.async {
dragging = false
}
}
print("init ItemProvider")
return provider
}
.contextMenu {
Button("Close Menu") {
dragging = false
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(dragging ? Color.gray : Color.white)
}
}
class ItemProvider: NSItemProvider {
var didEnd: (() -> Void)?
deinit {
print("deinit ItemProvider")
didEnd?()
}
}
EDIT (Dec. 2022): It seems like the code works in iOS 16.2. I still haven't found a good solution to this for earlier iOS versions.
