在macOS Catalyst上使用SwiftUI时,如何更改工具栏标题的颜色?

移动开发 2026-07-11

在我基于SwiftUI的 iOS应用中,我将导航栏/工具栏样式设为黑色。当然,这需要标题(以及其他内容)显示为白色/使用浅色模式才能看到。

虽然在iOS上可以正常工作,但在Catalyst上将 .toolbarColorScheme 设置为 .dark 并无影响。标题(以及其他内容,如ToolbarItems)始终显示为深色,因此在黑色背景上不可见。 “Some Page”在 iOS / Catalyst 的黑色背景上不可见
甚至在应用初始化阶段很早就使用 UINavigationBar.appearance() 全局设置样式也对Catalyst无效(因为这会影响应用中所有导航栏,因此也不可行)

在Catalyst中,使用自定义tile也会被完全忽略(仍显示“Some Page”)

.toolbar {
    ToolbarItem(placement: .principal) {
        Text("Custom Titel")
            .foregroundColor(.white)
            .font(.headline)
        }
    }
}

那么,在Catalyst下如何正确为工具栏设样式?

编辑: 感谢 @BenzyNeez的提示,我发现问题只在目标设置中的“Mac Catalyst Interface”选项处于激活状态、且选项为 "Optimized for Mac" 时才会出现。如果改用 "Scaled to match iPad",则按预期工作。不过,这会带来其他副作用。有没有办法在使用 "Optimized for Mac" 时改变标题颜色?

解决方案

你的问题已经证明,当选择部署选项 "Optimize for Mac" 时,修改器 .toolbarColorScheme 对Mac Catalyst不起作用。

同样,当使用该部署选项时,导航标题似乎不会被带有放置位置 .principalToolbarItem 替换。

因此需要一些变通方法。下面就一些问题给出处理思路:


应用深色模式

.preferredColorScheme(.dark) 确实对整个视图层级起作用。不过,这对你的情况可能并不有用,因为你仅仅想让工具栏使用深色调色方案。如果我理解正确,你希望主内容使用当前正在运行的配色方案。


设置工具栏背景

题中给出的代码使用 .toolbarBackground 将工具栏背景设为黑色。苹果现在不再鼓励这种做法,请参阅他们的 工具栏最佳实践指南

尽量减少对工具栏背景和着色控件的使用。 你使用的任何自定义背景和外观都可能覆盖或干扰系统提供的背景效果。相反,使用内容层来指示工具栏的颜色和外观。

如果把现有代码改为设置蓝色背景而不是黑色,你会发现它在iPad上(运行iPadOS 26时)并不理想。因此,符合该准则,我建议将背景应用到内容上。

下面的技术可用于仅填充顶部安全区域的背景:

mainContent
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(alignment: .top) {
        Color.blue
            .ignoresSafeArea()
            .frame(height: 0)
    }

显示标题

要在Mac Catalyst中显示自定义标题,以下方法可行:

  • 通过应用 .toolbar(removing: .title) 隐藏默认标题
  • 将自定义标题作为一个 ToolbarItem 显示,并设置放置位置为 .navigation
  • 隐藏项背后的“共享背景”
  • 明确将前景样式设为白色

对于iPad,不需要变通方法。因此,你可能需要为iOS和 Mac Catalyst使用不同的实现。文章 在SwiftUI(Mac Catalyst)项目中有条件地包含仅macOS的代码? 展示了实现这一点的方法。


把它放在一起看

下面是一个小示例,展示在蓝色背景上显示白色标题。它在iPad和 Mac Catalyst上都相当稳定地工作:

struct ToolbarModifiers: ViewModifier {
    func body(content: Content) -> some View {
        #if targetEnvironment(macCatalyst)
            content.toolbar(removing: .title)
        #else
            content.toolbarColorScheme(.dark, for: .navigationBar)
        #endif
    }
}

struct ContentView: View {
    let loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."

    private var titlePlacement: ToolbarItemPlacement {
        #if targetEnvironment(macCatalyst)
            .navigation
        #else
            .principal
        #endif
    }

    var body: some View {
        NavigationStack {
            ScrollView {
                VStack(spacing: 20) {
                    ForEach(0..<10) { _ in
                        Text(loremIpsum)
                            .font(.title3)
                    }
                }
                .padding()
            }
            .navigationTitle("Some Page")
            .navigationBarTitleDisplayMode(.inline)
            .modifier(ToolbarModifiers())
            .toolbar {
                ToolbarItem(placement: titlePlacement) {
                    Text("Custom Title")
                        .foregroundStyle(.white)
                        .font(.title3)
                        .fontWeight(.semibold)
                }
                .sharedBackgroundVisibility(.hidden)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(alignment: .top) {
                Color.blue
                    .ignoresSafeArea()
                    .frame(height: 0)
            }
        }
    }
}

iPad:

[动画

Mac Catalyst:

动画

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章