字节笔记本
2026年2月23日
SwiftUI 中使用 LazyVGrid 和 LazyHGrid 构建集合视图
SwiftUI 初始版本没有原生集合视图,开发者要么自己构建解决方案,要么使用第三方库。在今年的 WWDC 上,Apple 为 SwiftUI 框架引入了大量新功能,其中之一就是解决网格视图实现需求的方案。SwiftUI 现在为开发者提供了两个新的 UI 组件:LazyVGrid 和 LazyHGrid,分别用于创建垂直网格和水平网格。Apple 提到的 "Lazy" 意味着网格视图在需要之前不会创建项目。
本文将介绍如何使用 LazyVGrid 和 LazyHGrid 创建水平和垂直网格视图。这两个组件设计得非常灵活,开发者可以轻松创建各种类型的网格布局。我们还将探讨如何通过改变网格项的大小来实现不同的布局效果。
SwiftUI 网格布局基础
要创建网格布局(无论是水平还是垂直),可以按照以下步骤进行:
- 准备要在网格中展示的原始数据。例如,这里是一个我们要在演示应用中展示的 SF 符号数组:
private var symbols = ["keyboard", "hifispeaker.fill", "printer.fill", "tv.fill", "desktopcomputer", "headphones", "tv.music.note", "mic", "plus.bubble", "video"]- 创建一个 GridItem 数组来描述网格的外观。比如,网格应该有多少列?以下是描述三列网格的示例代码:
private var threeColumnGrid = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]- 使用 LazyVGrid 和 ScrollView 来布局网格。以下是代码片段:
ScrollView {
LazyVGrid(columns: threeColumnGrid) {
// 显示项目
}
}- 如果你想构建水平网格,可以使用 LazyHGrid:
ScrollView(.horizontal) {
LazyHGrid(rows: threeColumnGrid) {
// 显示项目
}
}使用 LazyVGrid 创建垂直网格
在了解了网格布局的基础知识后,让我们把代码付诸实践。假设你已经安装了 Xcode 12 beta,使用新的 App 模板创建一个新项目。
在 ContentView.swift 中,声明以下变量:
private var symbols = ["keyboard", "hifispeaker.fill", "printer.fill", "tv.fill", "desktopcomputer", "headphones", "tv.music.note", "mic", "plus.bubble", "video"]
private var colors: [Color] = [.yellow, .purple, .green]
private var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]我们要在一个三列网格中展示一组 SF 符号。要展示网格,请像这样更新 body 变量:
var body: some View {
ScrollView {
LazyVGrid(columns: gridItemLayout, spacing: 20) {
ForEach((0...9999), id: \.self) {
Image(systemName: symbols[$0 % symbols.count])
.font(.system(size: 30))
.frame(width: 50, height: 50)
.background(colors[$0 % colors.count])
.cornerRadius(10)
}
}
}
}我们使用 LazyVGrid 并告诉垂直网格使用 3 列布局。我们还指定行之间有 20 点的间距。在代码块中,我们有一个 ForEach 循环来展示总共 10,000 个图像视图。
现在图像的帧大小固定为 50×50 点。你可以像这样修改帧修饰符:
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 50)这样图像的宽度就会扩展以占据列的宽度。
使用 GridItem 改变网格布局(Flexible/Fixed/Adaptive)
让我们进一步了解 GridItem。你使用 GridItem 实例来配置 LazyHGrid 和 LazyVGrid 视图中的项目布局。之前,我们定义了三个 GridItem 实例的数组,每个都使用尺寸类型 .flexible()。flexible 尺寸类型使你能够创建三个等宽的列。
如果你想描述一个 6 列网格,可以像这样创建 GridItem 数组:
private var sixColumnGrid: [GridItem] = Array(repeating: .init(.flexible()), count: 6).flexible() 只是控制网格布局的尺寸类型之一。如果你想在一行中放置尽可能多的项目,可以使用 adaptive 尺寸类型:
private var gridItemLayout = [GridItem(.adaptive(minimum: 50))]adaptive 尺寸类型要求你指定项目的最小尺寸。在上面的代码中,每个网格项目的最小尺寸为 50。通过使用 .adaptive(minimum: 50),这指示 LazyVGrid 在一行中填充尽可能多的图像,使得每个项目的最小尺寸为 50 点。
除了 .flexible 和 .adaptive,如果你想创建固定宽度的列,也可以使用 .fixed。例如,你想将图像布局在两列中,第一列宽度为 100 点,第二列宽度为 150 点:
private var gridItemLayout = [GridItem(.fixed(100)), GridItem(.fixed(150))]你可以混合使用不同的尺寸类型来创建更复杂的网格布局。例如,你可以定义一个固定大小的 GridItem,后跟一个 adaptive 大小的 GridItem:
private var gridItemLayout = [GridItem(.fixed(150)), GridItem(.adaptive(minimum: 50))]在这种情况下,LazyVGrid 创建一个宽度为 150 点的固定大小列。然后,它尝试为剩余空间填充尽可能多的项目。
使用 LazyHGrid 创建水平网格
现在你已经创建了一个垂直网格,LazyHGrid 让将垂直网格转换为水平网格变得非常容易。水平网格的用法与 LazyVGrid 几乎相同,只是你将它嵌入到水平滚动视图中。此外,LazyHGrid 接受一个名为 rows 的参数而不是 columns。
因此,你可以重写几行代码,将网格视图从垂直方向转换为水平方向:
ScrollView(.horizontal) {
LazyHGrid(rows: gridItemLayout, spacing: 20) {
ForEach((0...9999), id: \.self) {
Image(systemName: symbols[$0 % symbols.count])
.font(.system(size: 30))
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 50, maxHeight: .infinity)
.background(colors[$0 % colors.count])
.cornerRadius(10)
}
}
}在预览中运行演示或在模拟器上测试。你应该会看到一个水平网格。最重要的是,这个网格视图自动支持 iPhone 和 iPad。
总结
SwiftUI 第一个版本中缺失的集合视图现在已经来了。SwiftUI 中引入的 LazyVGrid 和 LazyHGrid 让开发者可以用几行代码创建不同类型的网格布局。本文只是对这两个新 UI 组件的快速概述。我鼓励你尝试不同的 GridItem 配置,看看能实现什么样的网格布局。
原文链接:Building Collection Views in SwiftUI with LazyVGrid and LazyHGrid
作者:Simon Ng