SwiftUI小功能模块系列
0001、SwiftUI自定义Tabbar动画效果
0002、SwiftUI自定义3D动画导航抽屉效果
0003、SwiftUI搭建瀑布流-交错网格-效果
技术:SwiftUI3.0、瀑布流、交错网格
运行环境:
SwiftUI3.0 + Xcode13.4.1 + MacOS12.5 + iPhone Simulator iPhone 13 Pro Max
概述
使用SwiftUI搭建一个做一个瀑布流-交错网格
详细
一、运行效果
二、项目结构图
三、程序实现 - 过程
思路:
1.创建主窗口
2.再搭建瀑布流-交错网格页面
3.添加模型数据
4.添加一个测试瀑布流-交错网格的加减按钮
1.创建一个项目命名为 StaggeredGrid
1.1.引入资源文件
随机找十张图片即可
2. 创建一个虚拟文件New Group
命名为 View
3. 创建一个文件New File
选择SwiftUI View
类型 命名为Home
4. 创建一个文件New File
选择SwiftUI View
类型 命名为StaggeredGrid
5. 创建一个虚拟文件New Group
命名为 Model
6. 创建一个文件New File
选择SwiftUI View
类型 命名为Post
,并且删除预览视图 改造成一个模型
Code
ContentView - 主窗口
主要是展示主窗口
Home
//
// ContentView.swift
// Shared
//
// Created by 李宇鸿 on 2022/8/13.
//
import SwiftUI
struct ContentView: View {
var body: some View {
Home()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Home - 主页
思路
- 创建导航
- 创建瀑布流布局-交错网格
- 创建数据
- 创建瀑布流展示的View
//
// Home.swift
// StaggeredGrid (iOS)
//
// Created by 李宇鸿 on 2022/8/13.
//
import SwiftUI
struct Home: View {
@State var posts : [Post] = []
// To show dynamic
@State var columns : Int = 2
// Smooth Hero Effect
@Namespace var animation
var body: some View {
// 创建导航
NavigationView{
// 设置中心内容
StaggeredGrid(columns:columns, list:posts, content: { post in
// 在这里创建帖子卡片
PostCard(post: post)
.matchedGeometryEffect(id: post.id, in: animation)
.onAppear{
print(post.imageURL)
}
})
.padding(.horizontal)
.navigationTitle("Staggered Grid")
.toolbar{
ToolbarItem(placement: .navigationBarTrailing) {
Button{
columns += 1
}label: {
Image(systemName: "plus")
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button{
columns = max(columns - 1,1)
}label: {
Image(systemName: "minus")
}
}
}
// 动画……
.animation(.easeInOut, value: columns)
}
// 出现的时候
.onAppear{
for index in 1...10 {
posts.append(Post(imageURL: "post\(index)"))
}
}
}
}
struct Home_Previews: PreviewProvider {
static var previews: some View {
Home()
}
}
// 因为我们声明T为可识别的…
// 所以我们需要传递可识别集合/数组…
struct PostCard : View {
var post : Post
var body: some View{
Image(post.imageURL)
.resizable()
.aspectRatio(contentMode: .fit)
.cornerRadius(10)
}
}
StaggeredGrid.swift - 瀑布流-交错网格布局
主要是做 瀑布流-交错网格
思路
- 提供外界初始化操作 - 尽量提供额外多个属性 让外界调用 - 比如 : 网格的列数、间距、是否显示滚动条、数据的数量、网格的展示View
- 添加演示±的瀑布流-交错网格效果演示
- 展示瀑布流-交错网格内容 - 优化瀑布流-交错网格加载
//
// StaggeredGrid.swift
// StaggeredGrid (iOS)
//
// Created by 李宇鸿 on 2022/8/13.
//
import SwiftUI
// 自定义视图构建器…… Content 外界传递的视图
// T -> 是用来保存可识别的数据集合… 外界传递的列表模型数据
struct StaggeredGrid<Content: View, T : Identifiable>: View where T: Hashable {
// 它将从集合中返回每个对象来构建视图…
var content: (T) -> Content
var list : [T]
// 列……
var columns : Int
// 属性
var showsIndicators : Bool
var spacing : CGFloat
// 提供构造函数的闭包
init(columns: Int, showsIndicators: Bool = false,spacing : CGFloat = 10, list:[T], @ViewBuilder content: @escaping(T)->Content){
self.content = content
self.list = list
self.spacing = spacing
self.showsIndicators = showsIndicators
self.columns = columns
}
// 交错网格功能…
func setUpList()->[[T]]{
// 创建列的空子数组计数…
var gridArray : [[T]] = Array(repeating: [], count: columns)
// 用于Vstack导向视图的拆分数组…
var currentIndex : Int = 0
for object in list{
gridArray[currentIndex].append(object)
// increasing index count
// and resetting fi overbounds the columns count...
//增加索引计数
//和重置fi越界列计数…
if currentIndex == (columns - 1){
currentIndex = 0
}
else{
currentIndex += 1
}
}
return gridArray
}
var body: some View {
ScrollView(.vertical,showsIndicators: showsIndicators)
{
HStack(alignment:.top){
ForEach(setUpList(),id:\.self){ columnsData in
// 优化使用LazyStack…
LazyVStack(spacing:spacing){
ForEach(columnsData){ object in
content(object)
}
}
}
}
//只有垂直填充…
//水平填充将是用户可选的…
.padding(.vertical)
}
}
}
struct StaggeredGrid_Previews: PreviewProvider {
static var previews: some View {
// StaggeredGrid()
// 预览的是主窗口页面
ContentView()
}
}
Post - 模型
import SwiftUI
struct Post: Identifiable,Hashable {
var id = UUID().uuidString
var imageURL: String
}
demo源码
如需看源码,请点击下载!