SwiftUI 精通之路 11: 栅格布局

前言

做无名的小花,做快乐的小狗!

正文

进入正文,我们第一步还是首先创建我们的工程文件,我们打开我们创建的项目添加新的文件。Xcode 顶部的 File > New > File form Template... 快捷打开创建模板面板的的快捷键是 ⌘ + N.

当前章节中我们创建 名称为:GridBootcamp 的工程文件。

我们本章节主要学习 SwiftUI 中的栅格布局相关的知识,了解他的基本的概念以及如何去进行基本的使用,其次我们结合我们实际开发项目使用的案例场景。

SwiftUI 中的栅格布局是 SwiftUI 3.0 的时候进行引进,我们可以通过 LazyVStack 以及 LazyHStack 去管理我们定义的行以及列从而管理我们的内容。

栅格布局的基本概念

LazyVGrid:按垂直方向排列的栅格,内容可以纵向滚动。

LazyHGrid:按水平方向排列的栅格,内容可以横向滚动。

GridItem:定义栅格中的每个单元格的布局,决定列/行的大小和排列方式。

GridItem的常见模式

fixed: 固定大小的单元格。

fixed: 翻译意思是 固定 的意思

flexible: 自适应大小,可以扩展以填满可用空间。

flexible: 翻译意思是 灵活 的意思

adaptive: 可以在给定的宽度范围内放置尽可能多的单元格。

adaptive: 翻译意思是 自适应

我们现在了解了基本的参数,我们这边开开始着手创建我们的第一个栅格布局的案例吧,我们创建基本的栅格布局

  1. 我们以 LazyVStack 为例,创建纵向滚动的栅格布局,首先我们先定义
swift 复制代码
let columns: [GridItem] = [
    GridItem(.flexible(), spacing: 10, alignment: .center),
    GridItem(.flexible(), spacing: 10, alignment: .center),
    GridItem(.flexible(), spacing: 10, alignment: .center),
]

GridItem 使用 .flexible(),意味着每列会自动扩展,以填充父视图的可用宽度。

  1. 开始创建布局 LazyVStack 布局,其实你可以从这个 Lazy 你可以猜到,这个 SwiftUI 是对其进行懒加载优化的(就是如果数量特别多,没有显示在屏幕显示范围内的元素会进行不渲染)
swift 复制代码
ScrollView {
    LazyVGrid(columns: columns, spacing: 20) {
        ForEach(0..<50) { item **in******
            Text("Item \(item)")
                .frame(maxWidth: .infinity)
                .padding()
                .background(Color.blue)
                .cornerRadius(10)
                .foregroundColor(.white)
        }
    }
    .padding()
}

在当前代码中,我们通过 ScrollView 滚动视图构造器包裹创建滚动视图,其次我们通过 ForEach 去进行重复创建 50 个 Text 文本,哈哈哈,我不说你应该也是可以看出来吧!🙈

好的基础我们基本了解了!

我们开始进阶的使用案例:我们创建 响应式栅格布局

在某些情况下,我们需要基于屏幕的宽度动态调整栅格中的列数。我们可以使用 GridItem.adaptive(minimum: 100),来让栅格自适应屏幕大小。

这里我们设置当前列最小宽度为 100

swift 复制代码
// 进阶:自适应布局
let adaptiveColumns: [GridItem] = [
    GridItem(.adaptive(minimum: 100))
]

我们这边在原先基础代码的基础之上,创建我们先得布局列设置 adaptiveColumns, 我们将之前传入 LazyVStack 的参数 columns 更改为 adaptiveColumns.

GridItem(.adaptive(minimum: 100)) :列的宽度最小为 100,栅格会自动根据屏幕宽度调整列数。

这里我们使用我们之前介绍的 GridItem 常见的三种模式中的 .adaptive 去实现我们自适应的布局,在介绍时候我们也知道,这个模式是可以在给定的宽度范围内放置尽可能多的单元格

所以这个就特别使用我们创建类似类似于小红书或者抖音那种多列的布局。

我们最后再讲解下我们用的比较多的场景吧,那就是我们如何实现

对于更复杂的应用场景,你可以通过将栅格与其他布局(如 VStack、HStack)结合,创建灵活的 UI。也可以通过 LazyHGrid 来实现水平滚动的栅格布局。

我们还是通过创建垂直滚动的 LazyVStack 作为案例,所以我们首先定义我们的列元素。

swift 复制代码
// 进阶:复杂布局
let complexGridItem: [GridItem] = [
    GridItem(.fixed(120), spacing: 5, alignment: .leading),
    GridItem(.flexible())
]

GridItem(.fixed(120)) :第一列宽度固定为 120,第二列使用 .flexible() 填满剩余空间。

每个单元格中包含了图片和标题的组合布局,构建了一个复杂的视图。

当我们的屏幕大小进行变化的时候,第一列永远会定格在 120 的宽度,而第二列会进行自适应变化。

我们也可以将固定格式 .fixed.adaptive 进行 配合使用,那么就可以实现左侧固定,右侧的宽度自适应填满能装载的元素。

你可以看到,我们将 .adaptive 自适应应用到列格式中,设置其最小值为 80, 每个列之间间距设置为 10。

好的,关于栅格布局的基础应用方面就讲解到这里,希望对你有帮助,最后我们实现的电商列表的实现案例放在下面,可以当做练习案例!

下章再见👋

延伸案例

swift 复制代码
import SwiftUI

struct Product {
    let name: String
    let price: Double
    let imageName: String
}

let products = [
    Product(name: "T - Shirt 1", price: 19.99, imageName: "tshirt1"),
    Product(name: "T - Shirt 2", price: 24.99, imageName: "tshirt2"),
    Product(name: "Jeans", price: 39.99, imageName: "jeans"),
    Product(name: "Sweater", price: 49.99, imageName: "sweater")
]

struct ProductListView: View {
    var body: some View {
        ScrollView {
            LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) {
                ForEach(products) { product in
                    VStack {
                        Image(product.imageName)
                          .resizable()
                          .aspectRatio(contentMode:.fit)
                          .frame(height: 200)
                        Text(product.name)
                        Text("$(product.price)")
                    }
                  .padding()
                }
            }
        }
    }
}
相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax