首页 > 解决方案 > SwiftUI 中默认展开的 List 或 OutlineGroup

问题描述

使用 SwiftUI 中的 List 或 OutlineGroup 如何在创建视图时使其部分(或全部)分支默认展开。这似乎可以通过具有绑定的 DisclosureGroup 实现。

这对于恢复状态或自定义视图以进行演示很有用。

标签: iosmacosswiftuiios14macos-big-sur

解决方案


的可重用版本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()
    }
}

推荐阅读