带徽章的 SwiftUI macOS 菜单栏图标
SwiftUI macOS menubar icon with badge
正如您从图中看到的那样,我有一个程序应该以 menubar
打开,我想知道是否可以添加一个 badge
,如图二所示menubar
,表示有notifications
.
我在文档中找不到任何内容。
你能帮帮我吗?
状态栏控制器
import AppKit
import SwiftUI
class StatusBarController {
@ObservedObject var userPreferences = UserPreferences.instance
private var statusBar: NSStatusBar
var statusItem: NSStatusItem
private var popover: NSPopover
init(_ popover: NSPopover) {
self.popover = popover
statusBar = NSStatusBar.init()
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
if let statusBarButton = statusItem.button {
statusBarButton.image = #imageLiteral(resourceName: "Fork")
statusBarButton.image?.size = NSSize(width: 18.0, height: 18.0)
statusBarButton.image?.isTemplate = true
statusBarButton.action = #selector(togglePopover(sender:))
statusBarButton.target = self
statusBarButton.imagePosition = NSControl.ImagePosition.imageLeft
}
}
@objc func togglePopover(sender: AnyObject) {
if(popover.isShown) {
hidePopover(sender)
}else {
showPopover(sender)
}
}
func showPopover(_ sender: AnyObject) {
if let statusBarButton = statusItem.button {
popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: NSRectEdge.maxY)
}
}
func hidePopover(_ sender: AnyObject) {
popover.performClose(sender)
}
}
AppDelegate
import Cocoa
import SwiftUI
@main
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBar: StatusBarController?
var popover = NSPopover.init()
var timer: Timer? = nil
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView()
popover.contentSize = NSSize(width: 360, height: 360)
popover.contentViewController = NSHostingController(rootView: contentView)
statusBar = StatusBarController.init(popover)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}
您必须手动
创建自定义徽章视图。在 drawRect
中,您必须调整徽章的位置和数字的大小。
class BadgeView: NSView {
var number : Int {
didSet {
if oldValue != number { needsDisplay = true }
}
}
init(frame frameRect: NSRect, number : Int) {
self.number = number
super.init(frame: frameRect)
}
required init?(coder: NSCoder) {
self.number = 0
super.init(coder: coder)
}
override func draw(_ dirtyRect: NSRect) {
let fillColor = NSColor.systemRed
let path = NSBezierPath(ovalIn: NSRect(x: 3, y: 4, width: 14, height: 14))
fillColor.set()
path.fill()
let one = "\(number)"
let attribs : [NSAttributedString.Key:Any] = [.font : NSFont.systemFont(ofSize: 11.0), .foregroundColor : NSColor.white]
let xOrigin = (number > 9) ? 3.5 : 6.5
one.draw(at: NSPoint(x: xOrigin, y: 4.5), withAttributes: attribs)
}
}
在控制器class中添加一个属性和一个设置数字的函数
private var badgeView : BadgeView?
func setBadge(num : Int)
{
if num == 0 {
if let view = badgeView {
view.removeFromSuperview()
badgeView = nil
}
} else {
if let badgeView = badgeView {
badgeView.number = num
} else {
badgeView = BadgeView(frame: NSRect(x: 0, y: 0, width: 19, height: 22), number: num)
statusItem.button!.addSubview(badgeView!)
}
}
}
正如您从图中看到的那样,我有一个程序应该以 menubar
打开,我想知道是否可以添加一个 badge
,如图二所示menubar
,表示有notifications
.
我在文档中找不到任何内容。
你能帮帮我吗?
状态栏控制器
import AppKit
import SwiftUI
class StatusBarController {
@ObservedObject var userPreferences = UserPreferences.instance
private var statusBar: NSStatusBar
var statusItem: NSStatusItem
private var popover: NSPopover
init(_ popover: NSPopover) {
self.popover = popover
statusBar = NSStatusBar.init()
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
if let statusBarButton = statusItem.button {
statusBarButton.image = #imageLiteral(resourceName: "Fork")
statusBarButton.image?.size = NSSize(width: 18.0, height: 18.0)
statusBarButton.image?.isTemplate = true
statusBarButton.action = #selector(togglePopover(sender:))
statusBarButton.target = self
statusBarButton.imagePosition = NSControl.ImagePosition.imageLeft
}
}
@objc func togglePopover(sender: AnyObject) {
if(popover.isShown) {
hidePopover(sender)
}else {
showPopover(sender)
}
}
func showPopover(_ sender: AnyObject) {
if let statusBarButton = statusItem.button {
popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: NSRectEdge.maxY)
}
}
func hidePopover(_ sender: AnyObject) {
popover.performClose(sender)
}
}
AppDelegate
import Cocoa
import SwiftUI
@main
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBar: StatusBarController?
var popover = NSPopover.init()
var timer: Timer? = nil
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView()
popover.contentSize = NSSize(width: 360, height: 360)
popover.contentViewController = NSHostingController(rootView: contentView)
statusBar = StatusBarController.init(popover)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
}
您必须手动
创建自定义徽章视图。在 drawRect
中,您必须调整徽章的位置和数字的大小。
class BadgeView: NSView {
var number : Int {
didSet {
if oldValue != number { needsDisplay = true }
}
}
init(frame frameRect: NSRect, number : Int) {
self.number = number
super.init(frame: frameRect)
}
required init?(coder: NSCoder) {
self.number = 0
super.init(coder: coder)
}
override func draw(_ dirtyRect: NSRect) {
let fillColor = NSColor.systemRed
let path = NSBezierPath(ovalIn: NSRect(x: 3, y: 4, width: 14, height: 14))
fillColor.set()
path.fill()
let one = "\(number)"
let attribs : [NSAttributedString.Key:Any] = [.font : NSFont.systemFont(ofSize: 11.0), .foregroundColor : NSColor.white]
let xOrigin = (number > 9) ? 3.5 : 6.5
one.draw(at: NSPoint(x: xOrigin, y: 4.5), withAttributes: attribs)
}
}
在控制器class中添加一个属性和一个设置数字的函数
private var badgeView : BadgeView?
func setBadge(num : Int)
{
if num == 0 {
if let view = badgeView {
view.removeFromSuperview()
badgeView = nil
}
} else {
if let badgeView = badgeView {
badgeView.number = num
} else {
badgeView = BadgeView(frame: NSRect(x: 0, y: 0, width: 19, height: 22), number: num)
statusItem.button!.addSubview(badgeView!)
}
}
}