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

SwiftUI macOS开发如何实现ToolbarItem绝对居中保留前后置项

macOS 三段式固定居中工具栏实现方案

SwiftUI 原生.toolbar的默认布局逻辑不会给.principal位置分配全局居中的布局优先级,才会出现后置项紧贴居中元素、居中元素随前置内容偏移的问题,可通过以下两种方案实现需求:

方案1:原生Toolbar调整(保留系统特性,推荐)

不需要完全废弃原生Toolbar,只要调整布局规则和placement使用方式即可,适配macOS 12+,保留系统工具栏的所有原生交互(自定义排序、全屏自适应、touch bar联动等)。

  • 布局规则:
    • 前置区域元素统一使用.navigation placement,不要混放其他位置
    • 居中区域使用.principal placement,给容器设置最大宽度撑满可用空间,同时设置最高布局优先级,避免被前后元素挤压偏移
    • 后置区域元素统一使用.primaryAction/.confirmationAction placement,不要使用.automatic placement
  • 实现代码:
.toolbar {
    // 前置(leading)区域
    ToolbarItem(placement: .navigation) {
        HStack(spacing: 12) {
            // 放所有前置按钮、控件
            Button {} label: { Image(systemName: "sidebar.left") }
            Button {} label: { Image(systemName: "arrow.backward") }
            Button {} label: { Image(systemName: "arrow.forward") }
        }
    }

    // 居中(centered)区域
    ToolbarItem(placement: .principal) {
        HStack {
            Spacer()
            // 放所有居中控件
            Button {} label: {
                Image(systemName: "star.fill")
                    .scaleEffect(1.5)
            }
            Spacer()
        }
        .frame(maxWidth: .infinity)
        .layoutPriority(.greatestFiniteMagnitude)
    }

    // 后置(trailing)区域
    ToolbarItem(placement: .primaryAction) {
        HStack(spacing: 12) {
            // 放所有后置按钮、控件
            Button {} label: { Image(systemName: "square.and.arrow.up") }
            Button {} label: { Image(systemName: "star") }
        }
    }
}

方案2:自定义标题栏工具栏(布局100%可控)

如果需要兼容更低系统版本,或者对居中精度要求极高(完全不受前后元素动态变化影响),可以放弃系统原生Toolbar,自定义标题栏视图实现布局。

  • 实现逻辑:
    • 隐藏系统原生标题栏/工具栏
    • 顶部自定义工具栏高度和系统工具栏一致,使用系统栏材质背景
    • 前后置区域分别左右对齐,居中元素用overlay锚定在工具栏绝对中心位置,完全不受前后内容宽度影响
  • 实现代码:
// 窗口修饰符:隐藏原生标题栏
.windowStyle(.hiddenTitleBar)

// 页面根视图
var body: some View {
    VStack(spacing: 0) {
        // 自定义工具栏
        HStack(spacing: 0) {
            // 前置区域
            HStack(spacing: 12) {
                Button {} label: { Image(systemName: "sidebar.left") }
                Button {} label: { Image(systemName: "arrow.backward") }
                Button {} label: { Image(systemName: "arrow.forward") }
            }
            .padding(.horizontal, 8)
            
            Spacer()
            
            // 后置区域
            HStack(spacing: 12) {
                Button {} label: { Image(systemName: "square.and.arrow.up") }
                Button {} label: { Image(systemName: "star") }
            }
            .padding(.horizontal, 8)
        }
        .frame(height: 52) // 匹配系统工具栏默认高度
        .background(.bar) // 使用系统半透明栏材质
        .overlay(alignment: .center) {
            // 居中元素直接锚定在父视图中心,完全不受前后元素影响
            Button {} label: {
                Image(systemName: "star.fill")
                    .scaleEffect(1.5)
            }
        }
        
        // 页面正文内容
        YourContentPage()
    }
    .ignoresSafeArea(.container, edges: .top) // 让工具栏贴合窗口顶部
}
  • 注意点:该方案需要自行实现窗口拖拽、全屏工具栏自动隐藏等系统特性,如果需要支持系统级工具栏自定义排序能力不建议使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:57:25