The Util Designer
SwiftUI List元件的基本使用
xcode 13.4.1, swift 5.5, iOS 15.4
2022-08-17
List元件一個列表容器,每行只能包含一個元件,並提供可選擇一個或多個元件的容器。
1. 我們可以用VStack佈局在創建一個列表。
import SwiftUI

struct ListViewExample: View {
    var body: some View {
        VStack {
            Text("One")
            Text("Two")
            Text("Three")
            Text("Four")
        }
    }
}
2. 現在把VStack改成List元件:
import SwiftUI

struct ListViewExample: View {
    var body: some View {
        List {
            Text("One")
            Text("Two")
            Text("Three")
            Text("Four")
        }
    }
}
改成List後,每行元件之間多了一個分隔線。
3. 若把List和ForEach結合一起用:
import SwiftUI

struct ListViewExample: View {
    
    var body: some View {
        List {
            ForEach(0...40, id:\.self) { index in
                Text("Item \(index)")
            }
        }
    }
}
從上面看到若元件太多超出一個屏幕能顯示的,List又提供了一個拖拉的功能。
以下講講使用List的新增item和刪除item。
4. 結合NavigationView,使我們可以在toolbar上增加一些按鈕。
import SwiftUI

struct ListViewExample : View {
    @State var items : [String] = ["One", "Two"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id:\.self) { item in
                    Text(item)
                }
            }
        }
    }
}
5. 用了List,只需使用一個onDelete方法,我們就可以做刪除item的功能,實現如下:
import SwiftUI

struct ListViewExample : View {
    @State var items : [String] = ["One", "Two"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id:\.self) { item in
                    Text(item)
                }
                .onDelete { indexSet in
                    self.items.remove(atOffsets: indexSet)
                }
            }
        }
    }
}
6. 使用NavigationView的toolbar加一個新增item的按鈕。
import SwiftUI

struct ListViewExample : View {
    @State var items : [String] = ["One", "Two"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id:\.self) { item in
                    Text(item)
                }
                .onDelete { indexSet in
                    self.items.remove(atOffsets: indexSet)
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        self.items.insert("Item", at: 0)
                    } label: {
                        Image(systemName: "plus")
                    }
                }
            }
        }
    }
}
現在我們可以增加或刪除一個item, 但按了+按鈕後,新的item就立即出現,但使用SwiftUI的動畫withAnimation就可以讓增加item時以動畫形式慢慢出現,而不是立即出現。
import SwiftUI

struct ListViewExample : View {
    @State var items : [String] = ["One", "Two"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id:\.self) { item in
                    Text(item)
                }
                .onDelete { indexSet in
                    self.items.remove(atOffsets: indexSet)
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        withAnimation {
                            self.items.insert("Item", at: 0)
                        }
                    } label: {
                        Image(systemName: "plus")
                    }
                }
            }
        }
    }
}
7. 使用NavigationView的toolbar增加一個EditButton按鈕,並實現List的onMove方法,就可以移動item的先後順序。
import SwiftUI

struct ListViewExample : View {
    @State var items : [String] = ["One", "Two"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id:\.self) { item in
                    Text(item)
                }
                .onDelete { indexSet in
                    self.items.remove(atOffsets: indexSet)
                }
                .onMove { indexSet, offset in
                    self.items.move(fromOffsets: indexSet, toOffset: offset)
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        withAnimation {
                            self.items.insert("Item", at: 0)
                        }
                    } label: {
                        Image(systemName: "plus")
                    }
                }
            }
        }
    }
}
8. 最後結合NavigationLink,就可以做出在列表與item詳細版面之間的切換。
import SwiftUI

struct ListViewExample : View {
    @State var items : [String] = ["One", "Two"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id:\.self) { item in
                    NavigationLink {
                        Text(item)
                    } label: {
                        Text(item)
                    }

                }
                .onDelete { indexSet in
                    self.items.remove(atOffsets: indexSet)
                }
                .onMove { indexSet, offset in
                    self.items.move(fromOffsets: indexSet, toOffset: offset)
                }
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        withAnimation {
                            self.items.insert("Item", at: 0)
                        }
                    } label: {
                        Image(systemName: "plus")
                    }
                }
            }
        }
    }
}