前言
List 是 SwiftUI 官方提供的一个组件,它用来展示多行单列的数据。类似于 UIKit 中的 UITableView,但它的使用要比前者更加简单、更加优雅。并且它提供了选择单个或者多个数据的能力。下面是它最简单的使用方式:
var body: some View {
List {
Text("第一条数据")
Text("第二条数据")
Text("第三条数据")
Text("第四条数据")
}
}
效果图如下:
支持动态数据
在我们日常开发中,很少有静态数据的列表,更多的情况是请求接口拿到数据再填充到表格中。下面是一个动态数据的例子,主要通过三个步骤来实现:
- 定义一个结构体来表示数据格式
- 声明一个变量来存储数据源
- 将数据源填充到 List 中来进行展示
代码如下:
// 第一步
struct Food: Identifiable {
let name: String
let id = UUID()
}
struct ListTest: View {
// 第二步
let foods = [Food(name: "Hamburg"), Food(name: "Chicken"), Food(name: "Fish"), Food(name: "Beef")]
var body: some View {
// 第三步
List {
ForEach(foods) { food in
Text(food.name)
}
}
}
}
因为 List 的构造器本身支持了 ForEach 的功能,所以 List 的代码可以简化成下面的:
var body: some View {
List(foods){
Text($0.name)
}
}
Tips: 定义的数据结构需要遵守 Identifiable。
带有 Section 的列表
对于需要分 Section 的列表,我们可以借助 ForEach 和 Section 来实现。示例代码如下:
struct FoodSection: Identifiable {
let type: String
let foods: [Food]
let id = UUID()
}
struct ListTest: View {
let sectionFoods = [ FoodSection(type: "主食", foods: [Food(name: "Hamburg"), Food(name: "Pizza")]),
FoodSection(type: "小食", foods: [Food(name: "Chicken"), Food(name: "Fish")])
]
var body: some View {
List {
ForEach(sectionFoods) { section in
Section(content: {
ForEach(section.foods) { food in
Text(food.name)
}
}, header: {
Text("Title \(section.type)")
})
}
}
}
}
首先,我们声明一个 FoodSection 的结构体来表示分区数据源的数据结构。接着,我们声明一个 sectionFoods 的常量来存储需要展示的数据。最后,在 List 中使用 ForEach 对 sectionFoods 进行遍历,使用 Section 组件,在 content 里面遍历 foods 字段进行食物名称的展示。然后取出每个 section 的 type 字段赋值给 header。
这样,就可以展示具有分区的数据列表了。
效果图如下:
支持单元格的单选和多选
如果要实现单元格的单选或者多选,我们需要声明一个 @State 修饰的变量来存储已选择的数据,然后使用 List 的这个初始化构造器:init(_:selection:rowContent:)。其它步骤和上述的基本使用并无差别:
struct ListTest: View {
let foods = [Food(name: "Hamburg"), Food(name: "Chicken"), Food(name: "Fish"), Food(name: "Beef")]
@State private var selections = Set<UUID>()
var body: some View {
NavigationStack {
List(foods, selection: $selections) {
Text($0.name)
}
.navigationTitle("菜单")
.toolbar {
EditButton()
}
}
Text("选择了\(selections.count)种食物")
}
}
为了演示效果,给 List 的外层包裹了 NavigationStack,对其不了解的可以看这里。
效果如下:
需要注意的是,该效果需要运行代码在模拟器中看,在实时预览的页面是看不到这个动态效果的。