如何用SwiftUI复刻macOS Feedback.app的工具栏UI?
复刻macOS Feedback/Mail风格的SwiftUI工具栏问题与解决方案
需求说明
- 内容栏(Content)和详情栏(Detail)拥有各自独立的工具栏
- 面板内容滚动至工具栏后方时,工具栏呈现模糊背景效果
- 仅当内容滚动至工具栏后方时,工具栏才显示模糊背景及底部分隔线
- 内容栏和详情栏的工具栏样式不得延伸至侧边栏区域
当前实现问题
已通过NavigationSplitView实现独立工具栏,但以下需求未解决:
- 无法实现内容滚动时工具栏背景的动态切换(模糊/透明)
- 使用
.toolbarBackground(...)虽能添加模糊效果,但会导致工具栏背景永久显示,且样式延伸至侧边栏
相关代码
原ContentView
struct ContentView: View { var body: some View { NavigationSplitView( sidebar: { self.toolbarView(name: "Sidebar", showDivider: false) }, content: { self.toolbarView(name: "Content") }, detail: { self.toolbarView(name: "Detail", showDivider: false) } ) } func toolbarView(name: String, showDivider: Bool = true) -> some View { VStack(spacing: 0.0) { if showDivider { Divider() } List { Text(name) } .toolbar { ToolbarItemGroup { VStack(alignment: .leading) { Text(name).font(.headline) Text("Subtitle").font(.subheadline).foregroundStyle(.secondary) } Spacer() Text(name) } } } } }
原App入口
@main struct NavigationSplitViewTestApp: App { var body: some Scene { WindowGroup { ContentView() } .windowToolbarStyle(.unified) .windowStyle(.hiddenTitleBar) .windowResizability(.contentMinSize) } }
原生控件实现方案
通过调整NavigationSplitView的配置及工具栏背景设置,可完全依赖系统原生行为实现需求:
修改后的ContentView
struct ContentView: View { var body: some View { NavigationSplitView( sidebar: { // 侧边栏移除工具栏,避免样式延伸 List { Text("Sidebar Item") } }, content: { toolbarView(name: "Content") }, detail: { toolbarView(name: "Detail") } ) } func toolbarView(name: String) -> some View { List { // 添加足够多内容以便测试滚动效果 ForEach(1...50, id: \.self) { index in Text("\(name) Item \(index)") } } .toolbar { ToolbarItemGroup { VStack(alignment: .leading) { Text(name).font(.headline) Text("Subtitle").font(.subheadline).foregroundStyle(.secondary) } Spacer() Text(name) } } // 关键设置:让系统自动根据滚动状态切换工具栏背景 .toolbarBackground(.automatic, for: .windowToolbar) } }
修改说明
- 移除侧边栏工具栏:直接给侧边栏设置独立的
List,不添加工具栏,确保工具栏样式不会覆盖到侧边栏区域。 - 启用动态工具栏背景:通过
.toolbarBackground(.automatic, for: .windowToolbar)让系统原生处理背景逻辑:- 当列表内容在顶部时,工具栏透明,内容直接显示在后方
- 当内容滚动至工具栏下方时,自动显示模糊背景及底部分隔线
- 添加可滚动内容:生成多条列表项,方便测试滚动时的背景切换效果
窗口配置保持
原App入口的窗口设置无需修改,.unified工具栏样式配合.hiddenTitleBar可完美匹配Feedback/Mail的外观风格。
效果验证
- 内容栏和详情栏各自拥有独立工具栏,互不干扰
- 滚动列表时,工具栏背景会动态切换:顶部透明、滚动后显示模糊效果及分隔线
- 侧边栏无工具栏,样式完全独立
内容的提问来源于stack exchange,提问作者arsenius
相关产品推荐
相关产品推荐

