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()
                }
            }
        }
    }
}
相关推荐
neter.asia15 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫15 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
光影少年34 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_36 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891138 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾39 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu41 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym1 小时前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫1 小时前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫1 小时前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js