如何用NavigationSplitView实现macOS备忘录应用同款导航布局?
针对你遇到的隐藏标题栏后工具栏与内容重叠、显示标题栏后各列视觉区分度不足的问题,可以通过以下步骤实现和备忘录完全一致的效果:
1. 为各列独立配置导航栈与工具栏背景
macOS备忘录的核心视觉特点是:左侧分组栏无独立工具栏,中间列表栏的工具栏与列表背景融合,右侧详情栏的工具栏与窗口背景一致,和内容区域形成区分。我们可以通过给每列嵌套NavigationStack,单独控制工具栏样式来实现:
中间内容列(DiaryListView)
struct DiaryListView: View { @Binding var selectedDiary: Diary? @Environment(\.horizontalSizeClass) var horizontalSizeClass var body: some View { NavigationStack { List(diaries) { diary in Text(diary.title) .onTapGesture { selectedDiary = diary } } .toolbar { Button(action: { /* 实现添加逻辑 */ }) { Image(systemName: "plus") } } // 显示工具栏背景并与列表背景统一,避免内容重叠 .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color(NSColor.controlBackgroundColor), for: .navigationBar) // 使用plain列表样式并微调顶部间隙,消除多余留白 .listStyle(.plain) .padding(.top, -1) .navigationTitle("日记") } } }
右侧详情列(DiaryView)
struct DiaryView: View { var diary: Diary? @Environment(\.horizontalSizeClass) var horizontalSizeClass var body: some View { NavigationStack { if let diary = diary { ScrollView { Text(diary.content) .padding() } } else { Text("选择一个日记") .foregroundColor(.secondary) } .toolbar { Button(action: { /* 实现编辑逻辑 */ }) { Image(systemName: "pencil") } } // 详情栏工具栏背景与窗口背景统一,和内容区域形成区分 .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color(NSColor.windowBackgroundColor), for: .navigationBar) .navigationTitle(selectedDiary?.title ?? "无选择") } } }
2. 调整主布局与窗口设置
保持隐藏系统标题栏的同时,配置NavigationSplitView的基础样式,并设置窗口默认尺寸避免布局错乱:
主布局(MainLayoutView)
struct MainLayoutView: View { @State private var selectedGroup: Group? @State private var selectedDiary: Diary? @State private var columnVisibility: NavigationSplitViewVisibility = .all @Environment(\.horizontalSizeClass) private var horzSizeClass var body: some View { NavigationSplitView(columnVisibility: $columnVisibility) { GroupListView(selectedGroup: $selectedGroup) .navigationTitle("分组") } content: { DiaryListView(selectedDiary: $selectedDiary) .environment(\.horizontalSizeClass, horzSizeClass) } detail: { DiaryView(diary: selectedDiary) .environment(\.horizontalSizeClass, horzSizeClass) } .navigationSplitViewStyle(.balanced) } }
WindowGroup设置
WindowGroup { MainLayoutView() .environmentObject(auth) } .windowStyle(.hiddenTitleBar) .windowResizability(.contentSize) .defaultSize(width: 1000, height: 600)
关键逻辑说明
- 每列嵌套
NavigationStack后,可独立控制导航栏/工具栏的样式,解决多列标题栏无法区分的问题。 - 通过
toolbarBackground设置背景色,让中间列工具栏与列表融合,详情列工具栏与窗口背景统一,完美复刻备忘录的视觉层次。 - 微调列表的padding和样式,消除隐藏标题栏后出现的内容重叠与间隙问题。
内容的提问来源于stack exchange,提问作者codecodecode
相关产品推荐
相关产品推荐

