SwiftUI 中的多级列表

Posted

技术标签:

【中文标题】SwiftUI 中的多级列表【英文标题】:Multiple level List in SwiftUI 【发布时间】: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 级嵌套。 【参考方案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
    

【讨论】:

以上是关于SwiftUI 中的多级列表的主要内容,如果未能解决你的问题,请参考以下文章

删除列表中的黑色填充(SwiftUI)

SwiftUI:无法删除列表中的行

SwiftUI:删除列表中的动画?

恢复列表 SwiftUI 中的底部填充

Xcode Playground 中的 SwiftUI 列表

swiftui 列表部分中的圆角