• 【SwiftUI模块】0003、SwiftUI搭建瀑布流-交错网格


    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()
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Home - 主页

    思路

    1. 创建导航
    2. 创建瀑布流布局-交错网格
    3. 创建数据
    4. 创建瀑布流展示的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)     
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    StaggeredGrid.swift - 瀑布流-交错网格布局

    主要是做 瀑布流-交错网格
    思路

    1. 提供外界初始化操作 - 尽量提供额外多个属性 让外界调用 - 比如 : 网格的列数、间距、是否显示滚动条、数据的数量、网格的展示View
    2. 添加演示±的瀑布流-交错网格效果演示
    3. 展示瀑布流-交错网格内容 - 优化瀑布流-交错网格加载
    
    //
    //  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()
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    Post - 模型

    import SwiftUI
    
    struct Post: Identifiable,Hashable {
        var id = UUID().uuidString
        var imageURL: String
        
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    netty系列之:kequeue传输协议详解
    数智随行 | 财务数字化转型的抓手:业务能力标准化
    Spring源码级笔记(二)
    前端基础:BFC
    Win11配置多个CUDA环境
    [蓝桥杯 2022 省 B] 刷题统计
    使用Docker本地安装部署Drawio绘图工具并实现公网访问
    LeetCode_单调栈_中等_456.132 模式
    阿里推出新品牌“瓴羊”,致力成为“数字化领头羊”
    Mac系统,webots和pycharm联合仿真,配置问题解决方案!
  • 原文地址:https://blog.csdn.net/qq_42816425/article/details/126325803