如何在 swiftUI 生命周期中为三列视图添加工具栏分隔符

2024-03-24

我正在寻找一种方法来实现像 Mail.app 这样的三列布局的工具栏。此外,Notes.app 使用几乎相同的工具栏,两个应用程序之间唯一重要的区别是 Notes.app 看起来像WindowStyle is a HiddenTitleBarWindowStyle和 Mail.app 看起来像Default|TitleBarWindowStyle.

以下应该是正确的:

  1. 如果侧边栏折叠,则会出现列表和详细视图
  2. The dividing line that separates the list from the detail view goes all the way up through the toolbar. (This could be achieved with a HiddenTitleBarWindowStyle) sidebar collapsed - fully divided view
  3. If the Title is too long to fit into the navigation list, the vertical dividing line will be broken: The list is still divided from the Detail View as before, but now the Toolbar looks like a DefaultWindowStyle with only a small Divider()-like line in the Toolbar. sidebar collapsed - divider line

哪个组合WindowStyle, WindowToolbarStyle and .toolbar我需要配置才能实现此设置吗?

EDIT

我注意到无法删除 Notes.app 显示的分隔线。不过,我在文档中没有找到对任何此类元素的引用。

代码示例

我已将问题简化为一个主要包含工具栏内容的简单应用程序。在我的原始代码中我使用两个嵌套NavigationViews,而在这个例子中我只使用了一个NavigationView有两个列表。但是,那Toolbar结果是一样的。

工具栏有DefaultWindowStyle

import SwiftUI

@main
struct ToolbarTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView(titleBarIsHidden: true)
        }
        .windowToolbarStyle(UnifiedWindowToolbarStyle())
        .commands {
            SidebarCommands()
        }
    }
}

struct ContentView: View {
    @State var destination: String = "Toolbar Test"
    @State var detail: String = ""
    
    var body: some View {
        NavigationView {
            List {
                Button(action: {self.destination = "Item with the identifier:  1"}, label: {
                    Text("Item 1")
                })
                .buttonStyle(DefaultButtonStyle())
                Button(action: {self.destination = "Item 2"}, label: {
                    Text("Item 2")
                })
                .buttonStyle(DefaultButtonStyle())
            }
            .listStyle(SidebarListStyle())
            List {
                NavigationLink(
                    destination: DetailView(text: "\(destination) – \(detail)").onAppear{self.detail = "Detail 1"},
                    label: {
                        Text("\(destination) – Detail 1")
                    })
                NavigationLink(
                    destination: DetailView(text: "\(destination) – \(detail)").onAppear{self.detail = "Detail 2"},
                    label: {
                        Text("\(destination) – Detail 2")
                    })
            }
            .listStyle(InsetListStyle())
            Text("\(destination) – \(detail)")
        }
        .navigationTitle(destination)
        .navigationSubtitle(detail)
        .toolbar(id: "nav") {
            ToolbarItem(id: "plus", placement: ToolbarItemPlacement.principal, showsByDefault: true) {
                HStack {
                    Button(action: {print("pressed")}, label: {
                        Image(systemName: "plus.circle")
                    })
                }
            }
            ToolbarItem(id: "spacer", placement: ToolbarItemPlacement.confirmationAction, showsByDefault: true) {
                HStack {
                    Spacer()
                }
            }
            ToolbarItem(id: "sidebar.end", placement: ToolbarItemPlacement.confirmationAction, showsByDefault: true) {
                Button(action: {print("pressed")}, label: {
                    Image(systemName: "sidebar.right")
                })
            }
        }
    }
}

这个例子将导致Toolbar永远不会显示分割整个整体的分割线Toolbar分为两部分。也是第一个ToolbarItem位于中心Toolbar。我尝试了所有ToolbarItemPlacement但都没有导致项目移动到标题附近的最左侧。

工具栏有HiddenTitleBarWindowStyle

@main
struct ToolbarTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentViewForHiddenTitleBar()
        }
        .windowStyle(HiddenTitleBarWindowStyle()) // added hidden title style
        .windowToolbarStyle(UnifiedWindowToolbarStyle())
        .commands {
            SidebarCommands()
        }
    }
}

struct ContentViewForHiddenTitleBar: View {
    @State var destination: String = "Toolbar Test"
    @State var detail: String = ""
    
    var body: some View {
        NavigationView {
            List {
                Button(action: {self.destination = "Item with the identifier:  1"}, label: {
                    Text("Item 1")
                })
                .buttonStyle(DefaultButtonStyle())
                Button(action: {self.destination = "Item 2"}, label: {
                    Text("Item 2")
                })
                .buttonStyle(DefaultButtonStyle())
            }
            .listStyle(SidebarListStyle())
            // add geometry reader to trim title width in toolbar
            GeometryReader { geometry in
                List {
                    NavigationLink(
                        destination: DetailView(text: "\(destination) – \(detail)").onAppear{self.detail = "Detail 1"},
                        label: {
                            Text("\(destination) – Detail 1")
                        })
                    NavigationLink(
                        destination: DetailView(text: "\(destination) – \(detail)").onAppear{self.detail = "Detail 2"},
                        label: {
                            Text("\(destination) – Detail 2")
                        })
                }
                // there is no title anymore so let's fake it.
                .toolbar(id: "list navigation") {
                    ToolbarItem(id: "title", placement: ToolbarItemPlacement.navigation, showsByDefault: true) {
                        VStack(alignment: .leading) {
                            Text(destination)
                                .font(.headline)
                                .frame(maxWidth: .infinity, alignment: .leading)
                            Text(detail)
                                .font(.subheadline)
                                .opacity(0.6)
                                .frame(maxWidth: .infinity, alignment: .leading)
                        }
                        .frame(width: geometry.size.width)
                    }
                }
            }
            .listStyle(InsetListStyle())
            Text("\(destination) – \(detail)")
        }
        .navigationTitle(destination)
        .navigationSubtitle(detail)
        .toolbar(id: "nav") {
            // primary action will place the item next to the divider line.
            ToolbarItem(id: "plus", placement: ToolbarItemPlacement.primaryAction, showsByDefault: true) {
                HStack {
                    Button(action: {print("pressed")}, label: {
                        Image(systemName: "plus.circle")
                    })
                }
            }
            ToolbarItem(id: "spacer", placement: ToolbarItemPlacement.confirmationAction, showsByDefault: true) {
                HStack {
                    Spacer()
                }
            }
            ToolbarItem(id: "sidebar.end", placement: ToolbarItemPlacement.confirmationAction, showsByDefault: true) {
                Button(action: {print("pressed")}, label: {
                    Image(systemName: "sidebar.right")
                })
            }
        }
    }
}

这个例子将导致Toolbar将始终显示全高分隔线。即使标题太长。因此一个GeometryReader加入。这很好,直到侧边栏折叠为止。的放置ToolbarItems不会是正确的。另外在定制时Toolbar有可能删除标题,但这应该是不可能的。


默认标题栏样式很好,您只需将工具栏项附加到顶部 NavigationView 的子视图,例如:

var body: some View {
    NavigationView {
        
        List {
            ...
        }
        .listStyle(SidebarListStyle())
        .toolbar {
            ToolbarItem {
                Button(action: { }, label: {
                    Image(systemName: "sidebar.right")
                })
            }
        }
        
        List {
            ...
        }
        .listStyle(InsetListStyle())
        .toolbar {
            ToolbarItem {
                Button(action: { }, label: {
                    Image(systemName: "plus.circle")
                })
            }
        }
        
        Text("\(destination) – \(detail)")
    }
    .navigationTitle(destination)
    .navigationSubtitle(detail)
}

我没有将任何工具栏项附加到第三列(Text)但您可以 - 只需确保将相同的工具栏项目附加到您的 DetailViews,因为当用户导航时,其工具栏将替换文本的工具栏。 (如果您不确定我的意思,请尝试一下,您很快就会明白我在说什么:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 swiftUI 生命周期中为三列视图添加工具栏分隔符 的相关文章

随机推荐

  • Mac App Store 应用程序 iTMSTransporter 错误

    我正在尝试将我的 pkg 文件发送给 Apple 但系统显示 Transporter 正在搜索更新的软件组件 并且该进程始终在运行 无法停止 这是我的活动日志 看起来像是上传错误 我已经安装了 iTMSTransporter 1 7 7 p
  • Spring 的 Azure Pipeline Gradle 构建失败

    我尝试通过 Yaml 管道在 Azure 上构建和部署 Spring API 但我在 spring 应用程序 gradle 构建期间收到错误消息 Error home vsts work 1 s gradlew failed with re
  • ionic 5 强制浏览器应用程序的浅色主题

    我已经构建了这个应用程序https cvirus app https cvirus app并在浏览器上构建和部署 在 Android 手机上的 Chrome 浏览器上 它会呈现深色背景 因为默认情况下似乎应用了深色主题 我想在任何地方强制使
  • Postgres LIKE 将列值作为子字符串

    我正在尝试编写一个 WHERE 语句 该语句将匹配列值是另一个字符串的子字符串的行 例如 我可能有一个event记录与name现场Edward Sharpe 我想做这样的事情 SELECT FROM events WHERE name LI
  • 如何在 X 秒后应用 window.close() ?

    我有一个弹出窗口 其中包含 onclick 操作 可以在按下提交按钮时关闭该框
  • UIBezierPath 的橡皮擦

    我正在使用 UIBezierPath 在 iPad 应用程序中进行免费手绘 我想用橡皮擦乌贝济耶路径 questions tagged uibezierpath 不过 我想only擦除其路径中的图形 我cannot使用路径颜色作为背景颜色
  • htmlspecialchars 输出空白

    同时使用 htmlspecialchars 和 htmlentities 会导致项目的空白输出 例如 符号甚至单个 引号 显然 这绝对没用 但是在不使用 html 字符的情况下输出数据会导致 和 都出现此符号 出现这种情况有什么原因吗 这是
  • 填充在 iE 中不起作用?

    我希望内容周围 元素边框内有空间 http www w3schools com CSS css padding asp http www w3schools com CSS css padding asp 我使用了 cellpadding
  • Objectify 查询结果与数据存储查看器结果不一致的问题?

    我正在编写一个基于 TodoMVC angularjs 的示例项目 http todomvc com http todomvc com 并使用带有 Google App Engine Cloud Endpoint 的后端 api 当从 Ap
  • 从 shell 脚本更改 php.ini 值

    我是 shell 脚本的新手 我正在运行 Vagrant 发现自己需要在 php ini 中调整这些设置 upload max filesize 120M post max size 120M max execution time 200
  • 如何在codeigniter中获取父类别的所有子类别和孙类别?

    I want to get all the child and grandchild categories of a parent category upto any level My table structure goes like t
  • 防止未定义的参数

    所以我使用一个对象来传递我的可选变量 如下所示 var foo function options var options options provide a default so that var bar options bar 42 th
  • 为什么 C# 6 中声明表达式被删除?

    在 C 6 的预览中 Microsoft 引入了用于声明内联参数的语法糖 如本文所示 http odetocode com blogs scott archive 2014 09 15 c 6 0 features part 3 decla
  • Java中如何按顺序播放音频文件?

    因此 对于我正在开发的应用程序 我有一堆音频文件 根据某些变量的状态 这些文件可能会也可能不会播放 并且它们播放的顺序也可能会改变 我了解的基础知识setOnCompletionListener 但我无法找出使用它的最佳方法 截至目前 如果
  • 如何使用命令行更改 MySQL 表的外键

    如何使用命令行更改 MySQL 中的现有表 将外键设置到另一个表 你必须放弃现有的foreign key并创建另一个 例如这样 ALTER TABLE my table DROP FOREIGN KEY my key ALTER TABLE
  • xsd 和 xsi 有什么区别?

    到底有什么区别XML 架构文档 and XML 模式实例 xmlns xsd http www w3 org 2001 XMLSchema xmlns xsi http www w3 org 2001 XMLSchema instance
  • 将一列中的文本拆分为每行的多列[重复]

    这个问题在这里已经有答案了 我有以下数据集 Class Range Value A 6 8 19 B 1 3 14 C 5 16 10 D 4 7 5 我想将每个类别的范围分成两列 为此 我使用了该函数str split fixed如下 m
  • Delphi7,按向上键时进行形状​​跳跃

    我想在玩家按下UP键时进行形状 跳跃 所以我能想到的最好的就是这个 但我使用的方法很糟糕并且有问题 形状坐标 shape1 top 432 procedure TForm1 FormKeyDown Sender TObject var Ke
  • 强制整个网站使用 HTTPS 是好做法还是坏做法?

    我有一个网站 当所有内容都采用 HTTPS 身份验证 Web 服务等 时 该网站运行良好 如果我混合使用 http 和 https 则需要更多编码 跨域问题 我似乎没有看到很多完全采用 HTTPS 的网站 所以我想知道这样做是否是一个坏主意
  • 如何在 swiftUI 生命周期中为三列视图添加工具栏分隔符

    我正在寻找一种方法来实现像 Mail app 这样的三列布局的工具栏 此外 Notes app 使用几乎相同的工具栏 两个应用程序之间唯一重要的区别是 Notes app 看起来像WindowStyle is a HiddenTitleBa