Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply a context menu to buttons in a SwiftUI list row?

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.

enter image description here

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()
        }
    }
}
like image 432
Benjamin Angeria Avatar asked Apr 14 '20 14:04

Benjamin Angeria


People also ask

What is context menu in SwiftUI?

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.

How do I remove a row from a list in Swift?

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.

How to show a list of restaurants in swiftuilist?

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.

How to trigger context menu when people touch the row?

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.


1 Answers

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()
        }
    }
}
like image 123
Ofcourse Avatar answered Sep 21 '22 20:09

Ofcourse