I implement a NSMenu with NSMenuItem and set custom view to it. When menu is scrollable, mouse hovering on ▼ button to scroll will cause some menuItem disappear (or not draw correctly). Hope someone give me some help. I will appreciate that.
Here's video about this issue: https://streamable.com/obrbon
Here's my code:
private func setupMenuItemView(_ menu: NSMenu) {
let menuItemHeight: CGFloat = 20
let menuWidth = frame.width
let textFieldPadding: CGFloat = 10
for menuItem in menu.items {
guard !menuItem.title.isEmpty else { continue }
let menuItemView = MenuItemView(frame: NSRect(x: 0, y: 0, width: Int(menuWidth), height: menuItemHeight))
let textField = MenuItemTextField(labelWithString: menuItem.title)
textField.frame = NSRect(
x: textFieldPadding,
y: (menuItemView.frame.height-textField.frame.height)/2,
width: menuWidth-textFieldPadding*2,
height: textField.frame.height
)
textField.lineBreakMode = .byTruncatingTail
menuItemView.addSubview(textField)
menuItemView.toolTip = menuItem.title
menuItem.view = menuItemView
menuItem.target = self
menuItem.action = #selector(onMenuItemClicked(_:))
}
}
fileprivate class MenuItemView: NSView {
override func mouseUp(with event: NSEvent) {
guard let menuItem = enclosingMenuItem else { return }
guard let action = menuItem.action else { return }
NSApp.sendAction(action, to: menuItem.target, from: menuItem)
menuItem.menu?.cancelTracking()
}
override func draw(_ dirtyRect: NSRect) {
guard let menuItem = enclosingMenuItem else { return }
if menuItem.isHighlighted {
NSColor.alternateSelectedControlColor.set()
} else {
NSColor.clear.set()
}
NSBezierPath.fill(dirtyRect)
super.draw(dirtyRect)
}
}
fileprivate class MenuItemTextField: NSTextField {
override var allowsVibrancy: Bool {
return false
}
}
After calling setupMenuItemView()
, i call menu.popup()
.
Hope this information helps.
I was unable to get your posted code to work correctly. The demo below is an alternative which uses a popUpContextual menu with subclassed text fields embedded in the menuItem views (note that the view associated with each menuItem is used and a custom view class is not created). Text alignment and truncation is functional. Menu width is also flexible and may be set to match width of the menu title field. The demo may be run in Xcode by copy/pasting source code into a newly added ‘main.swift’ file and additionally deleting Apple’s AppDelegate class.