English | 简体中文
解决 macOS 刘海屏菜单栏图标被隐藏的问题
macOS 自 2021 款 MacBook Pro 引入刘海屏后,菜单栏右侧的图标空间被严重压缩。当应用图标数量较多时,会被刘海遮挡而完全无法看到和点击,严重影响使用体验。
LingLongBar 是一个轻量级的菜单栏辅助工具,能够:
- 🔍 自动检测:扫描系统中所有第三方应用在菜单栏的图标
- 📥 智能收纳:将被刘海遮挡或超出可视区域的图标自动收纳到 LingLongBar 中
- 🖱️ 一键访问:点击 LingLongBar 菜单栏图标即可查看和操作所有被收纳的图标
- ⚙️ 可配置:支持自定义收纳阈值、显示数量、开机启动等参数
- 自动收纳:检测被刘海遮挡的图标并自动收纳
- 点击访问:收纳后的图标可一键点击恢复原应用
- 右键菜单:右键 LingLongBar 图标可快速打开设置或退出
- 设置面板:提供通用、外观、关于三个设置页签
- 开机启动:通过
SMAppService注册登录项,真正实现开机自启 - 数量显示:可在菜单栏图标旁显示已收纳图标数量
- 深浅色适配:跟随系统外观自动切换
- 多显示器支持:自动识别含刘海的屏幕(遍历
NSScreen.screens) - 性能优化:AX 扫描在后台线程执行,不阻塞 UI
- macOS 13.0 (Ventura) 或更高版本
- Xcode Command Line Tools
- Swift 5.9+
# 克隆仓库
git clone https://github.com/langhen5lin/LingLongBar.git
cd LingLongBar
# 执行构建脚本(自动复制应用图标)
bash build.sh
# 运行应用
open build/LingLongBar.app构建产物位于 build/LingLongBar.app。
图标使用 Swift 脚本生成(基于 CoreGraphics),如需调整设计:
# 修改脚本后重新生成
swift scripts/generate_icon.swift Resources/AppIcon.icns
# 然后重新构建应用
bash build.sh首次启动 LingLongBar 时,需要授予 辅助功能(Accessibility) 权限:
- 系统会自动弹出授权弹窗,点击「打开系统设置」
- 在「隐私与安全性 → 辅助功能」中开启 LingLongBar 开关
- 返回 LingLongBar,应用会自动检测权限并开始扫描
⚠️ 没有辅助功能权限时,LingLongBar 无法读取其他应用的菜单栏图标信息。
首次使用时,请将 LingLongBar 图标手动移动到顶部菜单栏最右侧(靠近电池、WiFi 图标),避免图标被系统隐藏:
- 按住 ⌘ 键
- 将 LingLongBar 图标拖拽到菜单栏最右侧
macOS 在菜单栏空间不足时会从最左侧开始隐藏状态栏图标,若 LingLongBar 图标被隐藏,将无法点击打开收纳面板。将其放在最右侧可确保始终可见。
- 点击菜单栏 LingLongBar 图标:在菜单栏下方展开长条形收纳面板,横向查看被隐藏的图标
- 点击收纳的图标:打开对应应用(或其菜单栏下拉菜单)
- 右键菜单栏 LingLongBar 图标:打开设置或退出应用
- 右键收纳的图标:打开应用、在 Finder 中显示、退出应用
| 选项 | 说明 |
|---|---|
| 自动收纳超出的菜单栏图标 | 开启后自动收纳被刘海遮挡的图标 |
| 收纳阈值 | 控制图标数量过多时开始收纳(预留参数) |
| 开机自动启动 | 通过系统登录项跟随系统启动 |
| 显示收纳数量 | 在菜单栏图标旁显示已收纳的数字 |
LingLongBar/
├── Sources/LingLongBar/
│ ├── LingLongBarApp.swift # 应用入口(@main)
│ ├── AppDelegate.swift # 应用代理、状态栏图标、弹窗与设置窗口管理
│ ├── AppConstants.swift # 全局常量(bundleID、阈值等)
│ ├── Models/
│ │ ├── StatusItemInfo.swift # 状态栏图标数据模型
│ │ └── AppPreferences.swift # 用户偏好设置(持久化 + 登录项注册)
│ ├── Services/
│ │ ├── MenuBarScanner.swift # 菜单栏图标扫描核心(基于 Accessibility API)
│ │ ├── StatusItemManager.swift # 收纳逻辑管理(判断可见/收纳)
│ │ ├── NotchDetector.swift # 刘海屏检测与可用宽度计算(支持多显示器)
│ │ └── Localization.swift # 本地化取词(跟随系统/中文/英文)
│ └── Views/
│ ├── CollapsedMenuView.swift # 收纳面板 SwiftUI 视图
│ └── SettingsView.swift # 设置页面 SwiftUI 视图
├── Resources/
│ ├── AppIcon.icns # 应用图标(10 个尺寸)
│ ├── en.lproj/ # 英文本地化资源
│ └── zh-Hans.lproj/ # 中文本地化资源
├── scripts/
│ └── generate_icon.swift # 图标生成脚本
├── Info.plist # 应用配置
├── LingLongBar.entitlements # 应用沙箱与权限配置
├── Package.swift # Swift Package Manager 配置
├── build.sh # 构建脚本
└── README.md
NotchDetector 遍历所有屏幕,找出有刘海的(safeAreaInsets.top > 0),然后基于屏幕宽度比例估算刘海尺寸,计算右侧菜单栏的可用宽度边界。
MenuBarScanner 利用 macOS Accessibility API:
- 遍历
NSWorkspace中的运行应用 - 通过
AXExtrasMenuBar属性获取每个应用的状态栏图标 - 读取图标的
frame、description等属性 - 扫描在 后台线程 执行,结果回主线程更新
- 使用 确定性 UUID(基于 bundleID + identifier 的 FNV-1a 哈希)保证同一图标多次扫描 ID 稳定
StatusItemManager 根据图标在菜单栏中的实际位置分类:
- 系统图标(
com.apple.*):始终视为可见,不收纳 - 第三方图标:
frame.width == 0:已被 macOS 隐藏,需收纳frame.maxX < 屏幕右侧菜单栏左边界(即刘海右侧区域):图标被刘海遮挡,需收纳- 其余视为可见
边界由 NotchDetector.getRightMenuBarLeftBoundary() 计算。为避免图标在边界附近因微小
位置波动而反复横跳,分类带有滞回(hysteresis);当图标 frame 连续稳定时则直接按边界
硬判断,避免图标被滞回永久卡在旧状态。
- 收纳面板使用
NSPopover展示,呈现在顶部菜单栏下方的长条样式 - 收纳图标横向排列在一行,图标过多时可横向滚动
- 点击收纳图标:先关闭收纳面板,激活目标应用后触发其菜单栏操作,保证下拉菜单保持打开
- 设置窗口使用
NSWindow+NSHostingView嵌入 SwiftUI 视图
通过 ServiceManagement.SMAppService.mainApp 注册/注销登录项,开关状态与系统设置中的「登录项」实时同步。
欢迎提交 Issue 和 PR!
- Fork 本仓库
- 创建特性分支:
git checkout -b feature/your-feature - 提交更改:
git commit -m 'Add some feature' - 推送分支:
git push origin feature/your-feature - 提交 Pull Request
- 使用 Swift 5.9+ 特性
- 优先使用 SwiftUI 与 Combine
- 保持文件单一职责
- 注释使用中文,便于国内开发者阅读
- 使用
os.Logger记录日志,避免print
- 支持手动拖拽排序收纳图标
- 支持自定义收纳面板尺寸
- 支持图标分组管理
- 国际化(中英文)
- 菜单栏图标右键可直接退出单个应用
- 支持多显示器
- 开机自动启动(SMAppService)
- 后台线程扫描,UI 无卡顿
本项目基于 MIT License 开源。
- macOS Accessibility API 提供的强大能力
- SwiftUI 与 AppKit 混合开发的可能
- 图标生成脚本灵感来自原生 CoreGraphics 绘制
LingLongBar 通过 macOS Accessibility API 读取其他应用的菜单栏图标信息,仅在本地使用,不收集任何数据。请确保在使用时遵守所在地区的相关法律法规。