如何解决如何在 swiftUI 生命周期中为三列视图添加工具栏分隔符 带有 Toolbar 的工具栏带有 ToolbarItemPlacement 的工具栏
我正在寻找一种方法来实现像 Mail.app 这样的三列布局的工具栏。此外,Notes.app 使用几乎相同的工具栏,两个应用程序之间唯一重要的区别是 Notes.app 看起来像 WindowStyle
是一个 HiddenTitleBarWindowStyle
而 Mail.app 看起来像一个 {{1} }.
以下应该是正确的:
- 如果侧边栏折叠,则有一个列表和详细信息视图
- 将列表与详细视图分开的分隔线一直向上穿过工具栏。 (这可以通过
Default|TitleBarWindowStyle
实现) - 如果标题太长而无法放入导航列表,则垂直分隔线将被破坏:列表仍像以前一样从详细信息视图中划分出来,但现在工具栏看起来像一个
HiddenTitleBarWindowStyle
,只有工具栏中的一条类似DefaultwindowStyle
的小线。
实现此设置需要Divider()
、WindowStyle
和WindowToolbarStyle
配置的哪个组合?
编辑
我注意到无法删除 Notes.app 显示的分隔线。不过,我还没有在文档中找到对任何此类元素的引用。
代码示例
我已将问题归结为一个主要包含工具栏内容的简单应用程序。在我的原始代码中,我使用了两个嵌套的 .toolbar
,而在示例中我只使用了一个 NavigationView
和两个列表。但是,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",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 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,label: {
Image(systemName: "sidebar.right")
})
}
}
}
}
始终显示全高分隔线。即使标题太长。因此添加了 Toolbar
。这很好,直到侧边栏崩溃。 GeometryReader
的位置将不正确。此外,在自定义 toolbaritems
时,可能会删除标题,但这是不可能的。
解决方法
默认标题栏样式很好,您只需要将工具栏项附加到顶部 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,因为当用户导航。 (如果你不确定我的意思,试试看,你很快就会明白我在说什么:)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。