【问题标题】:Multiple level List in SwiftUISwiftUI 中的多级列表
【发布时间】:2020-07-21 10:37:23
【问题描述】:

我正在使用 SwiftUI 开发一个项目。我想创建类似的东西,

我目前使用的代码:

TaskListView

struct TaskListView: View {
    var tasks: [Task] = Task.all()
    
    var body: some View {
        List {
            ForEach(self.tasks) {task in
                TaskView(task: task)
            }
        }
    }
}

TaskView

struct TaskView: View {
    @ObservedObject var task: Task
    
    var body: some View {
        VStack {
            Text(task.name)
            .font(.custom("Avenir Next Regular", size: 14))
            
            //Here.................
            if !task.subtasks.isEmpty {
                Section {
                    ForEach(task.subtasks) {subtask in
                        TDTaskView(task: subtask)
                    }
                }.padding(.leading)
            }
        }
    }
}

Task 型号:

class Task: Identifiable, ObservableObject {
    var id: UUID = UUID()
    var name: String
    @Published var isCompleted: Bool = false
    var subtasks = [Task]()
    
    init(name: String, isCompleted: Bool = false, subtasks: [Task] = [Task]()) {
        self.name = name
        self.isCompleted = isCompleted
        self.subtasks = subtasks
    }
}

我尝试实现嵌套List 的方式现在可以在选择上正常工作。我是不是执行错了?

【问题讨论】:

  • 您需要使用部分。这个SwiftUI - nested list 会很有帮助。
  • 我已经试过了。但问题是我不知道嵌套级别。在链接示例中,它只是 2 级嵌套。

标签: ios swift swiftui swiftui-list


【解决方案1】:

您可以尝试递归创建项目:

struct ContentView: View {
    var tasks: [Task] = Task.all()

    var body: some View {
        List {
            TaskListView(tasks: tasks)
        }
    }
}
struct TaskListView: View {
    var tasks: [Task]

    var body: some View {
        ForEach(tasks, id: \.id) { task in
            TaskView(task: task)
        }
    }
}
struct TaskView: View {
    @ObservedObject var task: Task

    var body: some View {
        VStack {
            HStack {
                Circle().stroke() // replace with a custom control
                    .frame(width: 20, height: 20)
                Text(task.name)
                    .font(.custom("Avenir Next Regular", size: 14))
                Spacer()
            }
            if !task.subtasks.isEmpty {
                TaskListView(tasks: task.subtasks)
                    .padding(.leading)
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    你已经很接近了,我想说只改变两件事。

    首先,将 VStack 更改为 Group,这样各个“任务”将由 List 管理:

    var body: some View {
        VStack {
            Text(task.name)
            .font(.custom("Avenir Next Regular", size: 14))
    

    var body: some View {
        Group {
            Text(task.name)
            .font(.custom("Avenir Next Regular", size: 14))
    

    其次,将您的TDTaskView 更改为TaskView,这样您已经编写的代码将递归地构建您的任务列表:

            if !task.subtasks.isEmpty {
                Section {
                    ForEach(task.subtasks) {subtask in
                        TDTaskView(task: subtask)
                    }
                }.padding(.leading)
            }
    

            if !task.subtasks.isEmpty {
                Section {
                    ForEach(task.subtasks) {subtask in
                        TaskView(task: subtask)
                    }
                }.padding(.leading)
            }
    

    编辑

    这是完整的工作代码(非常接近您的原始代码):

    import SwiftUI
    
    struct ContentView: View {
        var tasks: [Task] = [Task(name: "thing"), Task(name: "more work"), Task(name: "Huge job", isCompleted: false, subtasks: [Task(name: "smaller job"), Task(name: "sorta small job")])]
        
        var body: some View {
            List {
                ForEach(self.tasks) {task in
                    TaskView(task: task)
                }
            }
        }
    }
    
    struct TaskView: View {
        @ObservedObject var task: Task
        
        var body: some View {
            Group {
                Text(task.name)
                    .font(.custom("Avenir Next Regular", size: 14))
                
                //Here.................
                if !task.subtasks.isEmpty {
                    Section {
                        ForEach(task.subtasks) {subtask in
                            TaskView(task: subtask)
                        }
                    }.padding(.leading)
                }
            }
        }
    }
    
    
    class Task: Identifiable, ObservableObject {
        var id: UUID = UUID()
        var name: String
        @Published var isCompleted: Bool = false
        var subtasks = [Task]()
        
        init(name: String, isCompleted: Bool = false, subtasks: [Task] = [Task]()) {
            self.name = name
            self.isCompleted = isCompleted
            self.subtasks = subtasks
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 2020-11-07
      • 1970-01-01
      • 2022-01-06
      • 2023-04-07
      • 1970-01-01
      相关资源
      最近更新 更多