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

如何用NavigationSplitView实现macOS备忘录应用同款导航布局?

实现macOS备忘录风格的NavigationSplitView布局

针对你遇到的隐藏标题栏后工具栏与内容重叠、显示标题栏后各列视觉区分度不足的问题,可以通过以下步骤实现和备忘录完全一致的效果:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 03:06:00