swiftUI与macOS开发:用SwiftUI开发menuBar

macOS的menuBar功能非常强大,我们在开发macOS应用的时候,经常需要利用menuBar实现功能。这篇文章主要是关于如何用swiftUI优雅地现在menuBar的popover。

最终效果图:

swiftUI与macOS开发:用SwiftUI开发menuBar_第1张图片

 

 

创建Popover

在AppDelegate文件中,声明一个NSPopover变量(下面的statusBarItem之后会用到)

var popover: NSPopover! var statusBarItem: NSStatusItem!

随后,在applicationDidFinishLaunching中, ContentView 初始化之后,加上

// Create the popover 
let popover = NSPopover() 
popover.contentSize = NSSize(width: 400, height: 400) 
popover.behavior = .transient //代表用户点击其他区域时popover自动消失 popover.contentViewController = NSHostingController(rootView: contentView) self.popover = popover

此时我们的AppDelegate文件应该长这样:

import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var popover: NSPopover!
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Create the popover
        let popover = NSPopover()
        popover.contentSize = NSSize(width: 400, height: 500)
        popover.behavior = .transient
        popover.contentViewController = NSHostingController(rootView: contentView)
        self.popover = popover
    }
    
}

 

这样我们即创建了一个Popover视图以及它的控制器,这个Popover的视图内容是我们的ContentView.swift里的内容。这样我们就可以在ContentView里用SwiftUI自由地定制我们的Popover。接下来我们要做的是,创建一个menuBarItem,当用户点击menuBarItem的按钮时,弹出我们已经写好的Popover。

self.statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
if let button = self.statusBarItem.button {
     button.image = NSImage(named: "Icon")
     button.action = #selector(togglePopover(_:))
}

还记得我们一开始声明了

var statusBarItem: NSStatusItem!

现在我们需要创建它,同时给它在menuBar设置个图标,绑定点击事件为togglePopover

self.statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
if let button = self.statusBarItem.button {
     statusBarItem.button?.title = "⏳"
     button.action = #selector(togglePopover(_:))
}

绑定togglePopover是为了在用户点击时弹出Popover

// Create the status item
@objc func togglePopover(_ sender: AnyObject?) {
     if let button = self.statusBarItem.button {
          if self.popover.isShown {
               self.popover.performClose(sender)
          } else {
               self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
          }
     }
}

最终,我们的AppDelegate文件长这样

import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var popover: NSPopover!
    var statusBarItem: NSStatusItem!
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Create the popover
        let popover = NSPopover()
        popover.contentSize = NSSize(width: 400, height: 500)
        popover.behavior = .transient
        popover.contentViewController = NSHostingController(rootView: contentView)
        self.popover = popover
        
        // Create the status item
        self.statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
        
        if let button = self.statusBarItem.button {
            statusBarItem.button?.title = "⏳"
            button.action = #selector(togglePopover(_:))
        }
    }
    
    @objc func togglePopover(_ sender: AnyObject?) {
        if let button = self.statusBarItem.button {
            if self.popover.isShown {
                self.popover.performClose(sender)
            } else {
                self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
            }
        }
    }
    
}
 
 
 
 

你可能感兴趣的:(Swift)