How to configure ContextMenu buttons for delete and disabled in SwiftUI?
I tried to configure the button in the contextMenu
, but it's not working.
Text("A label that have context menu")
.contextMenu {
Button(action: {
// remove it
}) {
Text("Remove")
.foregroundColor(.red) // Not working
Image(systemName: "trash")
}.disabled(true) // Not working
}
what I have:
What I'm seeking: (delete and call buttons)
I would create a UIAction
like the following in UIKit
but I can't find any modifier or anyway to bring this to the SwiftUI:
let delete = UIAction(title: "Remove", image: UIImage(systemName: "trash"), attributes: .destructive) { action in
// remove it
}
Solution 1:
All of the asked situations are now supported in iOS 15
Destructive: (works from iOS 15)
Set .destructive
as the role
argument of the button:
Button(role: .destructive) { // 👈 This argument
// delete something
} label: {
Label("Delete", systemImage: "trash")
}
Disabled: (works from iOS 14.2)
Add .disabled
modifier to the button.
Button {
// call someone
} label: {
Label("Call", systemImage: "phone")
}.disabled(true) // 👈 This modifier
Divider: (works from iOS 14)
Use a Divider()
view directly.
Full Demo:
⚠️ Remember! Do not use image
instead of systemImage
for showing an SFSymbol on the button!
Solution 2:
iOS 15
Starting with iOS 15 we can add a role
to a Button, so it can automatically adapt its appearance:
Here is an example:
Text("A label that have context menu")
.contextMenu {
Button(role: .destructive) {
print("removing...")
} label: {
Text("Remove")
Image(systemName: "trash")
}
}
Solution 3:
Toggling a boolean that determines if the view is visible works:
struct ContentView: View {
@State var textVisible = true
var body: some View {
Group {
if textVisible {
Text("Hello World")
.contextMenu {
Button(action: {
self.textVisible = false
}) {
HStack {
Text("Remove")
Image(systemName: "trash")
}
}
}
}
}
}
}
Of course, since the context menu is attached to the Text
that was removed, it will be permanently removed unless you having something else (e.g a Button
) that toggles the boolean (textVisible
in this case).
Edit: OP wanted to know how to make buttons in the context menu disabled/destructive (grey/red foreground colors), but I believe that as of October 20, 2019, SwiftUI has a bug that doesn't allow any buttons in the context menu to be any color other than red. Otherwise, setting the button as .disabled(true)
should give it a grey color and disable it, and setting the button's foreground color to red (foregroundColor(.red)
) should make the button destructive.