When I'm long-pressing on a button in list row, all of context menus for all buttons are shown. It looks like the whole list row is selected. How can I make it so that the context menu is shown only for the pressed button?
I've seen this question which is somewhat related, and tried BorderlessButtonStyle()
. It enables the indiviual buttons in the row to be clickable, but it doesn't solve the context menu problem. I've also tried using .onTapGesture()
instead of Button()
, but that didn't work either.
In the example below I'm expecting to see only Action for button 1 when long-pressing on Button 1 - but Action for button 2 is also shown.
struct ContentView: View {
var body: some View {
List {
ForEach((1..<3), content: { _ in
ListButton()
})
}
}
}
struct ListButton: View {
var body: some View {
HStack {
Spacer()
Button("Button 1") { }
.buttonStyle(BorderlessButtonStyle())
.contextMenu(menuItems: {
Text("Action for button 1")
})
Spacer()
Button("Button 2") { }
.buttonStyle(BorderlessButtonStyle())
.contextMenu(menuItems: {
Text("Action for button 2")
})
Spacer()
}
}
}
A context menu in SwiftUI is a menu of options that appears when the user performs a long press over a view on which a menu has been configured. Each menu item will typically contain a Button view configured to perform an action when selected, together with a Text view and an optional Image view.
In the menu, it provides two action buttons for users to choose: Delete and Favorite. When selected, the Delete button will remove the row from the list. The Favorite button will mark the selected row with a star indicator. SwiftUI has made it very simple to implement a context menu.
After opening the SwiftUIList.xcodeproj file, run the project or preview it in the canvas. The app should show you a list of restaurants. Editor’s note: If you’re new to SwiftUI and don’t know how to present a list, check out our SwiftUI tutorial for beginners.
We want to trigger the context menu when people touch and hold any of the rows. In the menu, it provides two action buttons for users to choose: Delete and Favorite. When selected, the Delete button will remove the row from the list. The Favorite button will mark the selected row with a star indicator.
You could use Menu
instead of ContextMenu
and use the label of the menu to display your button; as alternative solution.
However, to give the buttons gesture more priority than the row itself, you can add .highPriorityGesture(TapGesture())
to the end of you buttons.
You can achieve what you want by using Menu
instead of ContextMenu like this:
struct ListButton: View {
var body: some View {
HStack {
Spacer()
Button("Button 1") { }
.buttonStyle(BorderlessButtonStyle())
.contextMenu(menuItems: {
Text("Action for button 1")
})
Spacer()
// Here I used menu instead of the button 2
Menu {
Text("Action for button 2")
} label: {
Button("Button 2") { }
.buttonStyle(BorderlessButtonStyle())
}.highPriorityGesture(TapGesture())
Spacer()
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With