SwiftUI 中默认展开的 List 或 OutlineGroup
List or OutlineGroup expanded by default in SwiftUI
SwiftUI 中的List 或OutlineGroup 如何在创建视图时使其部分(或全部)分支默认展开。这似乎可以通过具有绑定的 DisclosureGroup 实现。
这对于恢复状态或自定义演示视图很有用。
我也在搜索这个,我相信 OutlineGroup 不支持这个。相反,我已经转移到 DisclosureGroup,OutlineGroup 将其用于其实现,并直接支持扩展布尔绑定以及允许嵌套:
struct ToggleStates {
var oneIsOn: Bool = false
var twoIsOn: Bool = true
}
@State private var toggleStates = ToggleStates()
@State private var topExpanded: Bool = true
var body: some View {
DisclosureGroup("Items", isExpanded: $topExpanded) {
Toggle("Toggle 1", isOn: $toggleStates.oneIsOn)
Toggle("Toggle 2", isOn: $toggleStates.twoIsOn)
DisclosureGroup("Sub-items") {
Text("Sub-item 1")
}
}
}
示例来自 https://developer.apple.com/documentation/swiftui/disclosuregroup
OutlineGroup
的可重用版本,其中可扩展性受到控制。
import SwiftUI
struct NodeOutlineGroup<Node>: View where Node: Hashable, Node: Identifiable, Node: CustomStringConvertible{
let node: Node
let childKeyPath: KeyPath<Node, [Node]?>
@State var isExpanded: Bool = true
var body: some View {
if node[keyPath: childKeyPath] != nil {
DisclosureGroup(
isExpanded: $isExpanded,
content: {
if isExpanded {
ForEach(node[keyPath: childKeyPath]!) { childNode in
NodeOutlineGroup(node: childNode, childKeyPath: childKeyPath, isExpanded: isExpanded)
}
}
},
label: { Text(node.description) })
} else {
Text(node.description)
}
}
}
struct ContentView: View {
var body: some View {
List {
NodeOutlineGroup(node: data, childKeyPath: \.children, isExpanded: true)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct FileItem: Hashable, Identifiable, CustomStringConvertible {
var id: Self { self }
var name: String
var children: [FileItem]? = nil
var description: String {
switch children {
case nil:
return " \(name)"
case .some(let children):
return children.isEmpty ? " \(name)" : " \(name)"
}
}
}
let data =
FileItem(name: "users", children:
[FileItem(name: "user1234", children:
[FileItem(name: "Photos", children:
[FileItem(name: "photo001.jpg"),
FileItem(name: "photo002.jpg")]),
FileItem(name: "Movies", children:
[FileItem(name: "movie001.mp4")]),
FileItem(name: "Documents", children: [])
]),
FileItem(name: "newuser", children:
[FileItem(name: "Documents", children: [])
])
])
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
非常好,Paul B.,谢谢。
但我想对显示的行有更多的控制。所以我稍微扩展了你的解决方案:
struct NodeOutlineGroup<Node, Content>: View where Node: Hashable, Node: Identifiable, Node: CustomStringConvertible, Content: View {
let node: Node
let childKeyPath: KeyPath<Node, [Node]?>
@State var isExpanded: Bool = true
let content: (Node) -> Content
var body: some View {
if node[keyPath: childKeyPath] != nil {
DisclosureGroup(
isExpanded: $isExpanded,
content: {
if isExpanded {
ForEach(node[keyPath: childKeyPath]!) { childNode in
NodeOutlineGroup(node: childNode, childKeyPath: childKeyPath, isExpanded: isExpanded, content: content)
}
}
},
label: { content(node) })
} else {
content(node)
}
}
}
使用情况:
struct ContentView: View {
var body: some View {
List {
NodeOutlineGroup(node: data, childKeyPath: \.children, isExpanded: true) { node in
Text(node.description)
}
}
}
}
SwiftUI 中的List 或OutlineGroup 如何在创建视图时使其部分(或全部)分支默认展开。这似乎可以通过具有绑定的 DisclosureGroup 实现。
这对于恢复状态或自定义演示视图很有用。
我也在搜索这个,我相信 OutlineGroup 不支持这个。相反,我已经转移到 DisclosureGroup,OutlineGroup 将其用于其实现,并直接支持扩展布尔绑定以及允许嵌套:
struct ToggleStates {
var oneIsOn: Bool = false
var twoIsOn: Bool = true
}
@State private var toggleStates = ToggleStates()
@State private var topExpanded: Bool = true
var body: some View {
DisclosureGroup("Items", isExpanded: $topExpanded) {
Toggle("Toggle 1", isOn: $toggleStates.oneIsOn)
Toggle("Toggle 2", isOn: $toggleStates.twoIsOn)
DisclosureGroup("Sub-items") {
Text("Sub-item 1")
}
}
}
示例来自 https://developer.apple.com/documentation/swiftui/disclosuregroup
OutlineGroup
的可重用版本,其中可扩展性受到控制。
import SwiftUI
struct NodeOutlineGroup<Node>: View where Node: Hashable, Node: Identifiable, Node: CustomStringConvertible{
let node: Node
let childKeyPath: KeyPath<Node, [Node]?>
@State var isExpanded: Bool = true
var body: some View {
if node[keyPath: childKeyPath] != nil {
DisclosureGroup(
isExpanded: $isExpanded,
content: {
if isExpanded {
ForEach(node[keyPath: childKeyPath]!) { childNode in
NodeOutlineGroup(node: childNode, childKeyPath: childKeyPath, isExpanded: isExpanded)
}
}
},
label: { Text(node.description) })
} else {
Text(node.description)
}
}
}
struct ContentView: View {
var body: some View {
List {
NodeOutlineGroup(node: data, childKeyPath: \.children, isExpanded: true)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct FileItem: Hashable, Identifiable, CustomStringConvertible {
var id: Self { self }
var name: String
var children: [FileItem]? = nil
var description: String {
switch children {
case nil:
return " \(name)"
case .some(let children):
return children.isEmpty ? " \(name)" : " \(name)"
}
}
}
let data =
FileItem(name: "users", children:
[FileItem(name: "user1234", children:
[FileItem(name: "Photos", children:
[FileItem(name: "photo001.jpg"),
FileItem(name: "photo002.jpg")]),
FileItem(name: "Movies", children:
[FileItem(name: "movie001.mp4")]),
FileItem(name: "Documents", children: [])
]),
FileItem(name: "newuser", children:
[FileItem(name: "Documents", children: [])
])
])
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
非常好,Paul B.,谢谢。 但我想对显示的行有更多的控制。所以我稍微扩展了你的解决方案:
struct NodeOutlineGroup<Node, Content>: View where Node: Hashable, Node: Identifiable, Node: CustomStringConvertible, Content: View {
let node: Node
let childKeyPath: KeyPath<Node, [Node]?>
@State var isExpanded: Bool = true
let content: (Node) -> Content
var body: some View {
if node[keyPath: childKeyPath] != nil {
DisclosureGroup(
isExpanded: $isExpanded,
content: {
if isExpanded {
ForEach(node[keyPath: childKeyPath]!) { childNode in
NodeOutlineGroup(node: childNode, childKeyPath: childKeyPath, isExpanded: isExpanded, content: content)
}
}
},
label: { content(node) })
} else {
content(node)
}
}
}
使用情况:
struct ContentView: View {
var body: some View {
List {
NodeOutlineGroup(node: data, childKeyPath: \.children, isExpanded: true) { node in
Text(node.description)
}
}
}
}