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

Mac Catalyst实现NSToolbar透明并保留信号灯按钮调整能力

Mac Catalyst 实现透明NSToolbar并保留标题栏工具栏控制

一、实现透明NSToolbar + 保留UITitlebarToolbarStyle调整信号灯

要同时满足透明工具栏和通过UITitlebarToolbarStyle调整信号灯位置,可结合标题栏配置与工具栏私有视图调整(这类视图调整在Mac Catalyst中通常可通过审核):

  1. 配置窗口标题栏基础属性
    在UISceneDelegate的scene(_:willConnectTo:options:)方法中,设置标题栏透明、隐藏标题并绑定自定义工具栏:
guard let windowScene = scene as? UIWindowScene else { return }

// 启用工具栏样式控制,调整信号灯位置
windowScene.titlebar?.toolbarStyle = .unifiedCompact // 可选.unified/.automatic等
windowScene.titlebar?.titleVisibility = .hidden
windowScene.titlebar?.backgroundColor = .clear

// 创建并绑定工具栏
let mainToolbar = NSToolbar(identifier: "MainToolbar")
mainToolbar.delegate = self
mainToolbar.displayMode = .iconOnly
mainToolbar.isVisible = true
windowScene.titlebar?.toolbar = mainToolbar
  1. 设置工具栏透明
    通过访问工具栏私有视图_toolbarView来设置透明背景:
if let toolbarView = mainToolbar.value(forKey: "_toolbarView") as? NSView {
    toolbarView.wantsLayer = true
    toolbarView.layer?.backgroundColor = NSColor.clear.cgColor
    // 隐藏默认分隔线
    toolbarView.subviews.forEach {
        if $0.className.contains("NSToolbarSeparatorView") {
            $0.isHidden = true
        }
    }
}
  1. 添加工具栏按钮(如完成按钮)
    通过NSToolbarDelegate协议实现自定义按钮:
extension YourSceneDelegate: NSToolbarDelegate {
    func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [.init("DoneButton")]
    }
    
    func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [.init("DoneButton")]
    }
    
    func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
        guard itemIdentifier == .init("DoneButton") else { return nil }
        
        let doneItem = NSToolbarItem(itemIdentifier: itemIdentifier)
        doneItem.label = "完成"
        doneItem.image = NSImage(systemSymbolName: "checkmark", accessibilityDescription: "完成")
        doneItem.target = self
        doneItem.action = #selector(onDoneTapped)
        return doneItem
    }
    
    @objc private func onDoneTapped() {
        // 处理按钮逻辑
    }
}

配置完成后,工具栏保持透明,toolbarStyle设置依然生效,可正常调整信号灯位置。

二、类似Electron 8的信号灯按钮调整功能实现

原生Mac Catalyst/Swift没有直接提供像Electron那样自由调整信号灯位置的API,但可通过两种方式实现类似效果:

1. 间接调整信号灯与工具栏间距

若仅需拉开信号灯与工具栏内容的距离,可在工具栏最左侧添加弹性空间项:

func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
    return [.flexibleSpace, .init("DoneButton")]
}

工具栏内容会被挤到右侧,信号灯与按钮间自动留出空隙,实现相对位置调整。

2. 自定义信号灯(复杂方案)

若需完全自定义信号灯位置(如移到窗口中间或右侧),需隐藏系统标题栏,自行绘制控制按钮并模拟系统行为:

  • 隐藏系统标题栏:windowScene.titlebar?.isHidden = true
  • 自定义最小化、最大化、关闭按钮,添加到窗口顶部
  • 通过NSWindow的performMiniaturize(_:)、performZoom(_:)、performClose(_:)方法模拟系统窗口操作
  • 监听鼠标事件实现窗口拖拽:
    NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown) { event in
        guard let window = self.windowScene?.windows.first else { return event }
        window.performDrag(with: event)
        return event
    }
    

该方案需处理大量系统交互细节,适合高度自定义需求,但开发成本较高。

内容的提问来源于stack exchange,提问作者Bluebyte

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 12:40:25