2

I would like to show contextMenu by clicking on the left mouse button? How to manually show view in SwiftUI?

Image(systemName: "book")
.contextMenu {
   Text("something1")
   Text("something2")
   Text("something3")
}
5
  • You mention mouse button, which makes me think this is about macOS, but you are also using Image(systemName:) which is not available in macOS. Which system are you building for? Commented Sep 25, 2019 at 17:17
  • I created iOS project and enabled Catalyst. Image:systemName works but not all images are available. Commented Sep 25, 2019 at 18:40
  • When you look at image declaration in SwiftUI you will find that this initialiser in not available: extension Image { @available(OSX, unavailable) public init(systemName: String) } Commented Sep 25, 2019 at 18:42
  • I already wrote that the compile considers the project as iOS here stackoverflow.com/q/57923102/4067700 Commented Sep 25, 2019 at 18:50
  • I added new question about emulating iOS apps on macOS stackoverflow.com/q/58104898/4067700 Commented Sep 25, 2019 at 19:00

2 Answers 2

7

You can use MenuButton with a menuButtonStyle to create a button which, when clicked, shows a menu. Seems to be Mac only currently.

MenuButton("Menu") {
    Button(action: {
      print("Clicked an item")
    }) {
        Text("Menu Item Text")                
    }
}.menuButtonStyle(BorderlessButtonMenuButtonStyle())
Sign up to request clarification or add additional context in comments.

1 Comment

Is there a way to adjust the size of the hit area? I am able to set a View as label, however it remains the same size.
2

The currently accepted answer uses MenuButton, which is now deprecated. Below is how to use the new Menu option.

This is possible now via Menu (iOS 14+, MacOS 11+)
Menus are covered in this WWDC video at ~11:15.

Playground Example:

import SwiftUI
import PlaygroundSupport

struct ContentView: View {
    
    var body: some View {
        HStack {
            // Other views
            Text("Example View 1")

            // Button, that when tapped shows 3 options
            Menu {
                Button(action: {
                    
                }) {
                    Label("Add", systemImage: "plus.circle")
                }
                Button(action: {
                    
                }) {
                    Label("Delete", systemImage: "minus.circle")
                }
                Button(action: {
                    
                }) {
                    Label("Edit", systemImage: "pencil.circle")
                }
            } label: {
                Image(systemName: "ellipsis.circle")
            }
        }
        .frame(width: 300, height: 300, alignment: .center)
    }
}

PlaygroundPage.current.setLiveView(ContentView())

If you wish to support MacOS 10.15 you could do something like:

if #available(iOS 14, macOS 11, *) {
    Menu {
        Button(action: {
            
        }) {
            Label("Add", systemImage: "plus.circle")
        }
        Button(action: {
            
        }) {
            Label("Delete", systemImage: "minus.circle")
        }
        Button(action: {
            
        }) {
            Label("Edit", systemImage: "pencil.circle")
        }
    } label: {
        Image(systemName: "ellipsis.circle")
    }
} else if #available(macOS 10.15, *) {
    MenuButton(
        label: Image(nsImage: NSImage(named: NSImage.actionTemplateName)!),
        content: {
            Button(action: {}) {
                HStack {
                    Image(nsImage: NSImage(named: NSImage.addTemplateName)!)
                    Text("Add")
                }
            }
            Button(action: {}) {
                HStack {
                    Image(nsImage: NSImage(named: NSImage.removeTemplateName)!)
                    Text("Delete")
                }
            }
            Button(action: {}) {
                HStack {
                    Image(nsImage: NSImage(named: NSImage.refreshTemplateName)!)
                    Text("Edit")
                }
            }
        })
        .menuButtonStyle(BorderlessButtonMenuButtonStyle())
} else {
    // Custom code here would be needed to support iOS 13 and MacOS 10.14
}

2 Comments

What about backwards compatibility and macOS 10.15? Menu API is not available there, can we still use MenuButton? I'm building an app and that troubles me.
@Gabb - I have added an example for macOS 10.15 compatibility.

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.