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

macOS应用开发如何隐藏全屏窗口的顶部标题栏分割线

问题描述

我遇到的问题是macOS应用全屏模式下的窗口头部栏显示问题。
当我将光标移动到屏幕顶部时,显示效果如下:
当前效果截图
但我想要实现的无顶部横线效果如下:
目标效果截图

隐藏窗口控制按钮的实现不存在难度,可通过如下代码完成:

wnd.standardWindowButton(NSWindow.ButtonType.closeButton)?.isHidden = true
wnd.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)?.isHidden = true
wnd.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true

但无法隐藏头部的那条分割线,检索相关技术资料未找到对应解决方案,猜测是否存在需要通过特殊方式禁用的额外“安全区域”?


已尝试方案

  • SwiftUI实现方案:
WindowGroup {
    SomeView()
        .edgesIgnoringSafeArea(.top)

}
.windowStyle( HiddenTitleBarWindowStyle() )

该方案仅能隐藏窗口化模式下的标题栏,对全屏模式下的头部横线无效。

  • AppKit接口修改NSWindow属性方案:
NSApp?.mainWindow?.styleMask.insert(NSWindow.StyleMask.unifiedTitleAndToolbar)        
NSApp?.mainWindow?.styleMask.insert(NSWindow.StyleMask.fullSizeContentView)        
NSApp?.mainWindow?.styleMask.insert(NSWindow.StyleMask.titled)
NSApp?.mainWindow?.toolbar?.isVisible = false
NSApp?.mainWindow?.titleVisibility = .hidden
NSApp?.mainWindow?.titlebarAppearsTransparent = true

上述代码同样无法去除全屏模式下的窗口头部横线。


解决方案

全屏模式下的顶部横线是macOS为全屏窗口单独渲染的标题栏分割线,常规的标题栏隐藏、透明属性只作用于窗口化状态,不会同步到全屏场景,核心需要做两步处理:一是关闭工具栏的基线分割线开关,二是在窗口进入全屏后遍历视图层级找到系统自动生成的分割线视图手动隐藏,两种常用场景的实现代码如下:

纯AppKit项目

首先在窗口初始化时配置基础属性:

// 基础标题栏配置
wnd.titleVisibility = .hidden
wnd.titlebarAppearsTransparent = true
wnd.toolbar?.isVisible = false
// 关键:关闭工具栏默认的基线分割线
wnd.toolbar?.showsBaselineSeparator = false
wnd.styleMask.insert([.fullSizeContentView, .unifiedTitleAndToolbar])

之后监听窗口进入全屏的系统通知,在回调里隐藏分割线:

NotificationCenter.default.addObserver(
    forName: NSWindow.didEnterFullScreenNotification,
    object: nil,
    queue: .main
) { notification in
    guard let window = notification.object as? NSWindow else { return }
    // 递归遍历视图层级查找系统分割线
    func locateDivider(in view: NSView) -> NSView? {
        for subview in view.subviews {
            // 系统分割线视图的类名固定包含"divider"字段
            if NSStringFromClass(type(of: subview)).lowercased().contains("divider") {
                return subview
            }
            if let target = locateDivider(in: subview) {
                return target
            }
        }
        return nil
    }
    // 从标题栏根视图开始查找
    let searchRoot = window.standardWindowButton(.closeButton)?.superview?.superview 
        ?? window.contentView?.superview 
        ?? window.contentView
    locateDivider(in: searchRoot)?.isHidden = true
}

SwiftUI项目

纯SwiftUI生命周期的项目可以通过视图修饰符注入上述逻辑,不需要额外创建NSWindowDelegate:

struct FullScreenNoDividerModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .edgesIgnoringSafeArea(.top)
            .onAppear {
                guard let mainWindow = NSApp.windows.first(where: \.isMainWindow) else { return }
                // 基础窗口配置
                mainWindow.titleVisibility = .hidden
                mainWindow.titlebarAppearsTransparent = true
                mainWindow.toolbar?.showsBaselineSeparator = false
                
                // 监听全屏事件
                NotificationCenter.default.addObserver(
                    forName: NSWindow.didEnterFullScreenNotification,
                    object: mainWindow,
                    queue: .main
                ) { _ in
                    func locateDivider(in view: NSView) -> NSView? {
                        for subview in view.subviews {
                            if NSStringFromClass(type(of: subview)).lowercased().contains("divider") {
                                return subview
                            }
                            if let target = locateDivider(in: subview) { return target }
                        }
                        return nil
                    }
                    let searchRoot = mainWindow.contentView?.superview ?? mainWindow.contentView
                    locateDivider(in: searchRoot)?.isHidden = true
                }
            }
    }
}

// 调用示例
@main
struct YourApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modifier(FullScreenNoDividerModifier())
        }
        .windowStyle(.hiddenTitleBar)
    }
}

注意:不要在窗口未进入全屏时修改分割线的hidden属性,系统在窗口切换布局状态(窗口化/全屏/分屏)时会重建标题栏视图,只需要在didEnterFullScreenNotification回调中执行隐藏逻辑即可,该方案兼容macOS 12.0及以上所有正式版本。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.20 16:15:50