PAYATHON 2026

SwiftUI 在 Mac Catalyst 下如何修改工具栏标题颜色?

数据阿明

结论

在题目描述的 Optimized for Mac 环境中,继续使用 .toolbarColorScheme(.dark) 或 UINavigationBar.appearance() 无法解决已复现的问题。如果需要单独控制标题颜色,可以尝试隐藏系统标题,再用放在 .navigation 位置的自定义 ToolbarItem 显示白色文字。

这种方式会替换显示的标题内容,不会直接修改系统标题的文字颜色。相关 API 还需要所用 SDK 和运行系统支持,不能保证适用于所有 Mac Catalyst 版本。

为什么 iOS 上有效,Catalyst 上却没有变化?

SwiftUI 的工具栏会在不同平台上映射到不同的系统界面。Apple 说明,SwiftUI 工具栏项目可以通过语义位置进入 Mac Catalyst 的 Mac 工具栏,因此屏幕上显示的标题不一定由 UINavigationBar 绘制。Apple:What’s new in Mac Catalyst

.toolbarColorScheme 设置的是工具栏的首选配色方案。Apple 文档指出,系统可能无法满足这个请求;只有指定工具栏的背景可见时,才会采用该配色请求。因此,它不能强制设置任意系统标题的颜色。Apple:toolbarColorScheme(_:for:)

题目中切换到 Scaled to match iPad 后恢复正常,有助于将排查范围缩小到界面模式差异,但不足以确定具体的系统缺陷或受影响版本。

保留 Optimized for Mac,改用自定义标题

可以按以下顺序处理:

  1. 用 .toolbar(removing: .title) 移除默认标题的显示。
  2. 将自定义标题放到 .navigation,避开题目中没有替换成功的 .principal。
  3. 直接将自定义 Text 设置为白色。
  4. 如果系统为该项目添加了共享玻璃背景,再用 .sharedBackgroundVisibility(.hidden) 隐藏它。

这些 API 分别用于移除默认项目、确定项目位置和控制共享背景。Apple 对 .navigation 的定义是:在 macOS 和 Mac Catalyst 中,项目位于工具栏的前缘、内联标题之前。因此,自定义标题的位置可能与原先居中的标题不同。Apple:toolbar(removing:)、Apple:title、Apple:navigation

下面的示例适用于 Mac Catalyst 26.0 及以上版本,并要求使用包含这些 API 的 SDK。它只处理标题,黑色背景继续沿用现有配置:

import SwiftUI

#if targetEnvironment(macCatalyst)
@available(macCatalyst 26.0, *)
struct CatalystToolbarTitle: ViewModifier {
    let title: String

    func body(content: Content) -> some View {
        content
            .toolbar(removing: .title)
            .toolbar {
                ToolbarItem(placement: .navigation) {
                    Text(title)
                        .font(.headline)
                        .foregroundStyle(.white)
                }
                .sharedBackgroundVisibility(.hidden)
            }
    }
}
#endif

在现有页面的 Catalyst 分支中,通过相应的可用性检查后应用:

#if targetEnvironment(macCatalyst)
if #available(macCatalyst 26.0, *) {
    page
        .navigationTitle("Some Page")
        .modifier(CatalystToolbarTitle(title: "Custom Titel"))
} else {
    page
        .navigationTitle("Some Page")
}
#else
page
    .navigationTitle("Some Page")
#endif

这里的 page 代表现有页面视图,需要放在原有导航容器中。较低版本的分支只保留原页面,标题颜色问题仍未解决。

.sharedBackgroundVisibility(.hidden) 应添加到 ToolbarItem 上。它控制项目的共享玻璃背景,不会将整个工具栏背景设置为黑色。Apple:sharedBackgroundVisibility(_:)

这套代码依据公开 API 组合而成,仍需在实际项目中验证。代码结构正确并不代表运行效果已经得到确认。

其他工具栏内容和深色模式怎么处理?

替换标题不会自动改变其他按钮、图标或菜单的颜色。应分别检查这些项目,为需要固定颜色的自定义内容显式设置样式,并确认禁用状态和非活动窗口状态仍然清楚可辨。

如果可以让整个窗口采用深色外观,可以尝试在窗口根视图设置 .preferredColorScheme(.dark)。它作用于最近的 presentation,例如窗口或 sheet,会影响正文内容,无法只限定在工具栏,也不能直接设置系统标题颜色。Apple:preferredColorScheme(_:)

验证时需要注意什么?

保留 Optimized for Mac,先在最小页面中验证默认标题是否消失、自定义标题是否出现,再逐步恢复其他 ToolbarItem。随后检查系统浅色与深色外观、窗口激活与失活、窗口缩窄以及页面导航后的表现。

如果当前 SDK 不支持示例中的 API,或目标系统上仍无法正确显示,可以保留系统管理的工具栏外观,将固定黑底白字的标题放到页面顶部的自定义内容区。不要把原生 macOS 的 NSWindow 外观代码直接套用到 Catalyst 项目;Catalyst 的窗口标题栏有自己的 UIWindowScene.titlebar 和 UITitlebar 配置入口。Apple:UITitlebar

备注:内容仅供参考。