Search code examples
swiftimageswiftuitooltippopover

Swift ui macOS popover on the button or on an image


enter image description here

I wish I could do such a thing as seen in the image.

I'm trying to use this piece of code but I'm not quite understanding how to fix it.

I wish I could use it on a Button or on an ImageMac which should be an image.

Can anyone help me out?

Code:

func showLittlePopoverWithMessage(sender: NSView, message: String) {
        let controller = NSViewController()
        controller.view = NSView(frame: CGRect(x: CGFloat(100), y: CGFloat(50), width: CGFloat(100), height: CGFloat(50)))

        let popover = NSPopover()
        popover.contentViewController = controller
        popover.contentSize = controller.view.frame.size

        popover.behavior = .transient
        popover.animates = true

        let invisibleWindow = NSWindow(contentRect: NSMakeRect(0, 0, 20, 5), styleMask: .borderless, backing: .buffered, defer: false)
        invisibleWindow.backgroundColor = .red
        invisibleWindow.alphaValue = 0

        //controller.view.addSubview(sender)
        popover.show(relativeTo: sender.bounds, of: sender as! NSView, preferredEdge: .maxY)
    }
#if os(macOS)
struct ImageMac: View {
    let symbol: String
    init(systemName: String) {
        self.symbol = [
            "star":         "☆",
            "star.fill":    "★",
            "heart":        "􀊴",
            "heart.fill":   "􀊵",
            "video":        "􀍉",
            "lock.fill":    "􀎡",
            "lock.open.fill":    "􀎥",
            "checkmark.seal.fill": "􀇻"
            ][systemName] ?? "?"
    }
    var body: some View { Text(symbol) }
}
#endif

ImageMac(systemName: "checkmark.seal.fill").foregroundColor(.blue)

Button(action: {}) {
   Text("Button")
}

Solution

  • Here is demo of possible approach. Prepared & tested with Xcode 11.7 / macOS 10.15.6

    demo

    struct ContentView: View {
        @State var isPopover = false
        var body: some View {
            VStack {
                Button(action: { self.isPopover.toggle() }) {
                    Image(nsImage: NSImage(named: NSImage.infoName) ?? NSImage())
                }.popover(isPresented: self.$isPopover, arrowEdge: .bottom) {
                         PopoverView()
                }.buttonStyle(PlainButtonStyle())
            }.frame(width: 800, height: 600)
        }
    }
    
    struct PopoverView: View {
        var body: some View {
            VStack {
                Text("Some text here ").padding()
                Button("Resume") {
                }
            }.padding()
        }
    }