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

SwiftUI 1.0中如何将应用标题栏宽度限定为指定区域(仿Apple Music)

在SwiftUI 1.0中实现类似Apple Music的窄版融合工具栏

嘿,我来帮你搞定这个问题!你想要的是类似Apple Music那种「工具栏与标题栏同排融合、且工具栏仅占据特定宽度」的效果,你的现有代码已经完成了标题栏透明、隐藏标题的基础配置,但要实现窄版布局,还得结合AppKit的底层操作来补全——毕竟SwiftUI 1.0对macOS的工具栏定制支持还比较有限。

核心实现思路

SwiftUI 1.0本身没法直接控制工具栏的宽度,所以我们需要:

  • 用NSToolbarDelegate自定义工具栏项,限制它的宽度范围
  • 将SwiftUI视图嵌入到NSHostingView中,作为工具栏的内容
  • 配置窗口的样式,让内容区域能延伸到标题栏,实现融合效果

完整代码示例

假设你是用传统的AppDelegate来管理窗口(SwiftUI 1.0在macOS上通常是这种结构),我们可以这样修改:

1. 窗口与工具栏基础配置

import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // 创建SwiftUI根视图
        let contentView = ContentView()

        // 创建窗口,必须添加.fullSizeContentView样式
        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.contentView = NSHostingView(rootView: contentView)
        
        // 你的原有标题栏配置,补充工具栏代理和样式
        let customToolbar = NSToolbar(identifier: "CustomMusicToolbar")
        customToolbar.showsBaselineSeparator = false
        customToolbar.delegate = self
        customToolbar.autosavesConfiguration = false // 禁止系统自动保存工具栏布局
        window.toolbar = customToolbar
        window.titleVisibility = .hidden
        window.titlebarAppearsTransparent = true
    }
}

2. 实现NSToolbarDelegate定制工具栏项

extension AppDelegate: NSToolbarDelegate {
    // 定义允许的工具栏项ID
    func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [.musicToolbarItem]
    }
    
    // 定义默认显示的工具栏项
    func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [.musicToolbarItem]
    }
    
    // 创建自定义工具栏项
    func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
        guard itemIdentifier == .musicToolbarItem else { return nil }
        
        let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
        // 将SwiftUI视图嵌入到NSHostingView中
        let toolbarContentView = NSHostingView(rootView: MusicToolbarContentView())
        toolbarItem.view = toolbarContentView
        
        // 设置工具栏项的固定宽度,控制它的占用范围(类似Apple Music的窄版效果)
        toolbarItem.minSize = CGSize(width: 350, height: 40)
        toolbarItem.maxSize = CGSize(width: 350, height: 40)
        
        return toolbarItem
    }
}

// 自定义工具栏项ID
extension NSToolbarItem.Identifier {
    static let musicToolbarItem = NSToolbarItem.Identifier("MusicToolbarItem")
}

3. 编写SwiftUI工具栏内容视图

struct MusicToolbarContentView: View {
    var body: some View {
        HStack(spacing: 12) {
            // 左侧图标+标题
            Image(systemName: "music.note.list")
                .font(.title2)
                .foregroundColor(.primary)
            Text("My Music")
                .font(.headline)
                .foregroundColor(.primary)
            
            Spacer()
            
            // 右侧操作按钮
            Button(action: { /* 搜索逻辑 */ }) {
                Image(systemName: "magnifyingglass")
                    .foregroundColor(.primary)
            }
            Button(action: { /* 侧边栏切换逻辑 */ }) {
                Image(systemName: "sidebar.left")
                    .foregroundColor(.primary)
            }
        }
        .padding(.horizontal, 16)
        .frame(height: 40)
    }
}

关键注意事项

  • .fullSizeContentView样式:这是实现标题栏与工具栏融合的核心,没有它,SwiftUI内容无法延伸到标题栏区域。
  • 工具栏项宽度控制:通过minSize和maxSize固定工具栏项的宽度,避免它自动撑满整个窗口宽度。
  • SwiftUI视图嵌入:用NSHostingView把SwiftUI视图包装成AppKit视图,才能放到NSToolbarItem里。
  • 窗口布局适配:如果需要窗口 resize 时动态调整工具栏宽度,可以在windowDidResize代理方法里更新toolbarItem.minSize和maxSize。

内容的提问来源于stack exchange,提问作者Trần Kim Dự

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:11:42