You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sonoma系统下NSMenuItem自定义字体keyEquivalent修饰符对齐异常求解

Sonoma系统中自定义字体NSMenuItem的keyEquivalent对齐问题解决方案

问题原因

Sonoma系统对NSMenuItem的文本渲染逻辑做了调整:当直接为attributedTitle设置自定义字体(如Kanit-Light)时,系统不会自动同步keyEquivalent(快捷键命令符号)的基线对齐属性,导致两者错位;而使用系统字体时,系统会统一处理标题与快捷键的布局匹配。

解决方法

方法1:直接设置NSMenuItem的font属性(推荐)

放弃设置attributedTitle,直接给菜单项目指定自定义字体,让系统自动处理标题和快捷键的对齐逻辑:

// 替换原attributedTitle设置代码
quitMenuItem.font = NSFont.settingsLightFont(withSize: 14.0)

这种方式会让系统保持标题文本与keyEquivalent的布局一致性,完全适配Sonoma的渲染规则。

方法2:修正attributedTitle的属性设置(若需保留复杂文本样式)

如果必须使用attributedTitle实现特殊文本样式,需显式添加基线对齐相关属性,确保自定义字体与系统快捷键符号的基线匹配:

let paraStyle: NSMutableParagraphStyle = NSMutableParagraphStyle()
paraStyle.lineBreakMode = .byTruncatingTail
paraStyle.alignment = .left // 显式设置对齐方式,与系统菜单默认一致

var titleAttributes: [NSAttributedString.Key : Any] = [
    .font: NSFont.settingsLightFont(withSize:14.0),
    .paragraphStyle: paraStyle,
    .baselineOffset: 0 // 强制设置基线偏移,消除自定义字体的基线差异
]

quitMenuItem.attributedTitle = NSAttributedString(
    string: NSLocalizedString("Quit", comment: ""),
    attributes: titleAttributes
)

方法3:自定义NSMenuItem子类重写绘制逻辑(极端场景)

如果上述方法都无效,可通过子类化NSMenuItem,重写drawKeyEquivalent(withFrame:in:)方法,手动调整keyEquivalent的绘制位置:

class CustomMenuItem: NSMenuItem {
    override func drawKeyEquivalent(withFrame frame: NSRect, in view: NSView) {
        // 调整frame的y坐标来修正对齐,根据自定义字体的基线差异计算偏移量
        var adjustedFrame = frame
        adjustedFrame.origin.y += 1 // 示例偏移值,需根据实际字体调整
        super.drawKeyEquivalent(withFrame: adjustedFrame, in: view)
    }
}

使用时将nib中的NSMenuItem类改为CustomMenuItem即可。

内容的提问来源于stack exchange,提问作者Babitha shetty k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 18:22:27