当前位置: 首页 > article >正文

iOS瀑布流布局的实现(swift)

在iOS开发中,瀑布流布局(Waterfall Flow)是一种常见的多列不等高布局方式,适用于图片、商品展示等场景。以下是基于UICollectionView实现瀑布流布局的核心步骤和优化方法:


一、实现原理

瀑布流的核心在于动态计算每个元素的位置,将其放置在当前高度最低的列中。通过自定义UICollectionViewLayout子类,结合数据源的动态高度计算,可实现灵活的布局效果。


二、实现步骤

1. 创建自定义布局类
  • 继承UICollectionViewFlowLayout:需自定义一个类(如WaterfallLayout),继承自UICollectionViewFlowLayout,并重写关键方法。
    class WaterfallLayout: UICollectionViewFlowLayout {// 声明属性,如记录每列的最大Y值private var columnHeights: [CGFloat] = []private var attributesArray: [UICollectionViewLayoutAttributes] = []
    }
    
2. 重写prepareLayout方法
  • 初始化布局属性:在此方法中计算每个Cell的位置和大小。
    override func prepare() {super.prepare()columnHeights = Array(repeating: sectionInset.top, count: numberOfColumns)attributesArray.removeAll()// 遍历所有元素,计算布局属性for item in 0..<collectionView!.numberOfItems(inSection: 0) {let indexPath = IndexPath(item: item, section: 0)guard let attributes = layoutAttributesForItem(at: indexPath) else { continue }attributesArray.append(attributes)}
    }
    
3. 动态计算Cell位置
  • 确定最短列:每次将新Cell插入当前高度最低的列。
    func shortestColumnIndex() -> Int {var minIndex = 0for i in 1..<columnHeights.count {if columnHeights[i] < columnHeights[minIndex] {minIndex = i}}return minIndex
    }
    
  • 计算Cell的Frame:根据列数、间距和动态高度确定每个Cell的位置。
    let columnIndex = shortestColumnIndex()
    let x = sectionInset.left + (itemWidth + minimumInteritemSpacing) * CGFloat(columnIndex)
    let y = columnHeights[columnIndex]
    let height = delegate?.collectionView(collectionView!, heightForItemAt: indexPath) ?? 100
    let frame = CGRect(x: x, y: y, width: itemWidth, height: height)
    
4. 处理滚动方向和内容尺寸
  • 设置内容尺寸:根据所有列的最大高度确定UICollectionView的内容高度。
    override var collectionViewContentSize: CGSize {let maxHeight = columnHeights.max() ?? 0return CGSize(width: collectionView!.bounds.width, height: maxHeight + sectionInset.bottom)
    }
    

三、性能优化

  1. 提前计算布局信息
    在数据加载阶段预计算所有Cell的高度和位置,避免滚动时重复计算。

  2. 图片缓存与异步加载
    使用第三方库(如SDWebImage)实现图片的异步加载和缓存,减少内存占用。

  3. Cell重用机制
    通过dequeueReusableCell(withReuseIdentifier:for:)重用Cell,避免频繁创建和销毁。

  4. 懒加载与分页加载
    仅加载可视区域内的Cell,滚动到底部时触发分页加载更多数据。

  5. 布局属性缓存
    prepareLayout中缓存所有布局属性,避免频繁调用layoutAttributesForItem


四、扩展功能示例

1. 动态列数与间距

通过代理方法支持动态调整列数和间距:

protocol WaterfallLayoutDelegate {func numberOfColumns(in collectionView: UICollectionView) -> Intfunc collectionView(_ collectionView: UICollectionView, heightForItemAt indexPath: IndexPath) -> CGFloat
}
2. 特殊元素全屏显示

在布局中识别特定Cell,为其分配整屏宽度,其他元素动态调整位置。


五、对比其他实现方案

  1. UIScrollView实现
    需手动管理Cell的重用和布局,复杂度较高,适合高度定制化需求。
  2. 多UITableView实现
    每列使用一个UITableView,但无法有效利用重用机制,性能较差。

总结

通过自定义UICollectionViewLayout实现瀑布流布局是最推荐的方式,既支持灵活布局,又利用系统级优化。开发者可根据需求扩展列数、间距、动态高度等功能,并通过缓存和异步加载提升性能。具体实现可参考开源项目(如豆瓣相册的DAWaterfallLayout)。

相关文章:

iOS瀑布流布局的实现(swift)

在iOS开发中&#xff0c;瀑布流布局&#xff08;Waterfall Flow&#xff09;是一种常见的多列不等高布局方式&#xff0c;适用于图片、商品展示等场景。以下是基于UICollectionView实现瀑布流布局的核心步骤和优化方法&#xff1a; 一、实现原理 瀑布流的核心在于动态计算每个…...

Spring Spring Boot 常用注解整理

Spring & Spring Boot 常用注解整理 先理解核心概念&#xff1a;什么是注解&#xff08;Annotation&#xff09;&#xff1f;第一部分&#xff1a;IOC&#xff08;控制反转&#xff09;和 DI&#xff08;依赖注入&#xff09;1. Component2. Service, Repository, Controll…...

c#建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能

# financial_建筑行业 建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能 # 开发背景 软件是给岳阳客户定制开发一款建筑行业流水账财务软件。提供工程签证单、施工日志、人员出勤表等信息记录。 # 财务管理系统功能描述 1.可以自行设置记账科目&#xff0c;做凭…...

让 Cursor 教我写 MCP Client

文章目录 1. 写在最前面2. 动手实现一个 MCP Client2.1 How 天气查询 Client2.1.1 向 Cursor 提问的艺术2.1.2 最终成功展示2.1.3 client 的代码 3. MCP 协议核心之一总结3.1 SSE vs WebSocket 4. 碎碎念5. 参考资料 1. 写在最前面 学习了 MCP Server 的实现后&#xff0c;刚好…...

反射, 注解, 动态代理

文章目录 单元测试什么是单元测试咱们之前是如何进行单元测试的&#xff1f; 有啥问题 &#xff1f;现在使用方法进行测试优点Junit单元测试的使用步骤删除不需要的jar包总结 反射认识反射、获取类什么是反射反射具体学什么&#xff1f;反射第一步&#xff1a;或者Class对象 获…...

vue vite 无法热更新问题

一、在vue页面引入组件CustomEmployeesDialog&#xff0c;修改组件CustomEmployeesDialog无法热更新 引入方式&#xff1a; import CustomEmployeesDialog from ../dialog/customEmployeesDialog.vue 目录结构&#xff1a; 最后发现是引入import时&#xff0c;路径大小写与目…...

【CustomPagination:基于Vue 3与Element Plus的高效二次封装分页器】

CustomPagination&#xff1a;基于Vue 3与Element Plus的高效二次封装分页器 在现代Web应用开发中&#xff0c;分页是处理大量数据列表时不可或缺的功能。Element Plus等UI库提供了基础的分页组件&#xff0c;但在大型项目中&#xff0c;为了追求极致的用户体验和视觉统一&…...

kafka connect 大概了解

kafka connect Introduction Kafka Connect is the component of Kafka that provides data integration between databases, key-value stores, search indexes, file systems, and Kafka brokers. kafka connect 是一个框架&#xff0c;用来帮助集成其他系统的数据到kafka…...

UniApp 在华为三折叠屏中的适配问题与最佳解决方案(rpx 实战指南)

随着折叠屏设备的普及&#xff0c;如华为 Mate Xs、Mate X3 等多形态设备越来越常见&#xff0c;开发者在 UniApp 项目中遇到的适配问题也变得复杂。本文将聚焦一个关键问题&#xff1a;在三折叠屏设备上&#xff0c;使用 px 单位造成页面显示异常&#xff0c;并给出最推荐的解…...

深度学习中的查全率与查准率:如何实现有效权衡

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4-turbo模型辅助生成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认…...

Docker从0到1:入门指南

目录 什么是DockerDocker的核心概念 容器(Container)镜像(Image)镜像层(Image Layers)Dockerfile仓库(Repository)数据卷(Volume)网络(Network) Docker架构Docker安装Docker基本命令实际应用场景Docker生态系统最佳实践常见问题 什么是Docker Docker是一个开源的应用容器引擎…...

Windows玩游戏的时候,一按字符键就显示桌面

最近打赛伯朋克 2077 的时候&#xff0c;不小心按错键了&#xff0c;导致一按字符键就显示桌面。如下&#xff1a; 一开始我以为是输入法的问题&#xff08;相信打游戏的人都知道输入法和奔跑键冲突的时候有多烦&#xff09;&#xff0c;但是后来解决半天发现并不是。在网上搜…...

Gemini 2.5 Flash和Pro预览版价格以及上下文缓存的理解

Gemini 2.5 Flash和Pro预览版价格 Gemini 2.5 Flash 预览版就是 Google 的最新 AI 大模型&#xff0c;能处理巨量内容。可以免费体验&#xff0c;但有次数和功能上的限制&#xff1b;付费层级才开放全部高级功能。价格也比传统 API 略有不同&#xff0c;尤其在“思考预算”“上…...

vue2 头像上传+裁剪组件封装

背景&#xff1a;最近在进行公司业务开发时&#xff0c;遇到了头像上传限制尺寸的需求&#xff0c;即限制为一寸证件照&#xff08;宽295像素&#xff0c;高413像素&#xff09;。 用到的第三方库&#xff1a; "vue-cropper": "^0.5.5" 完整组件代码&…...

unity 鼠标更换指定图标

1.准备两张图 要求图片导入设置如下 将 Texture Type 改为 Cursor 确保 Read/Write Enabled 已勾选 取消勾选 Generate Mip Maps 将 Filter Mode 设为 Point (保持清晰边缘) 将 Compression 设为 None (无压缩) 2.创建脚本&#xff0c;把脚本挂到场景中 &#xff0c;该…...

AI-02a5a5.神经网络-与学习相关的技巧-权重初始值

权重的初始值 在神经网络的学习中&#xff0c;权重的初始值特别重要。实际上&#xff0c;设定什么样的权重初始值&#xff0c;经常关系到神经网络的学习能否成功。 不要将权重初始值设为 0 权值衰减&#xff08;weight decay&#xff09;&#xff1a;抑制过拟合、提高泛化能…...

【springcloud学习(dalston.sr1)】Eureka单个服务端的搭建(含源代码)(三)

该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍&#xff08;含源代码&#xff09;&#xff08;一&#xff09; 这篇文章主要介绍单个eureka服务端的集群环境是如何搭建的。 通过前面的文章【springcloud学习(dalston.sr1)】…...

Node.js数据抓取技术实战示例

Node.js常用的库有哪些呢&#xff1f;比如axios或者node-fetch用来发送HTTP请求&#xff0c;cheerio用来解析HTML&#xff0c;如果是动态网页的话可能需要puppeteer这样的无头浏览器。这些工具的组合应该能满足大部分需求。 然后&#xff0c;可能遇到的难点在哪里&#xff1f;…...

[架构之美]Spring Boot集成MyBatis-Plus高效开发(十七)

[架构之美]Spring Boot集成MyBatis-Plus高效开发&#xff08;十七&#xff09; 摘要&#xff1a;本文通过图文代码实战&#xff0c;详细讲解Spring Boot整合MyBatis-Plus全流程&#xff0c;涵盖代码生成器、条件构造器、分页插件等核心功能&#xff0c;助你减少90%的SQL编写量…...

windows10 安装 QT

本地环境有个qt文件&#xff0c;这里是5.14.2 打开一个cmd窗口并指定到该文件根目录下 .\qt-opensource-windows-x86-5.14.2.exe --mirror https://mirrors.ustc.edu.cn/qtproject 执行上面命令 记住是文件名&#xff0c;记住不要傻 X的直接复制&#xff0c;是你的文件名 点击…...

WordPress 和 GPL – 您需要了解的一切

如果您使用 WordPress&#xff0c;GPL 对您来说应该很重要&#xff0c;您也应该了解它。查看有关 WordPress 和 GPL 的最全面指南。 您可能听说过 GPL&#xff08;通常被称为 WordPress 的权利法案&#xff09;&#xff0c;但很可能并不完全了解它。这是有道理的–这是一个复杂…...

计算机网络:什么是计算机网络?它的定义和组成是什么?

计算机网络是指通过通信设备和传输介质&#xff0c;将分布在不同地理位置的计算机、终端设备及其他网络设备连接起来&#xff0c;实现资源共享、数据传输和协同工作的系统。其核心目标是使设备之间能够高效、可靠地交换信息。 关键组成部分 硬件设备 终端设备&#xff1a;如计算…...

C++书本摆放 2024年信息素养大赛复赛 C++小学/初中组 算法创意实践挑战赛 真题详细解析

目录 C++书本摆放 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、运行结果 五、考点分析 六、 推荐资料 1、C++资料 2、Scratch资料 3、Python资料 C++书本摆放 2024年信息素养大赛 C++复赛真题 一、题目要求 1、编程实现 中科智慧科技…...

在scala中使用sparkSQL读入csv文件

以下是使用 Spark SQL&#xff08;Scala&#xff09;读取 CSV 文件的完整代码示例&#xff1a; scala import org.apache.spark.sql.SparkSession import org.apache.spark.sql.types._object CSVReadExample {def main(args: Array[String]): Unit {// 创建SparkSessionval…...

RabbitMQ 核心概念与消息模型深度解析(一)

一、RabbitMQ 是什么 在当今分布式系统盛行的时代&#xff0c;消息队列作为一种至关重要的中间件技术&#xff0c;扮演着实现系统之间异步通信、解耦和削峰填谷等关键角色 。RabbitMQ 便是消息队列领域中的佼佼者&#xff0c;是一个开源的消息代理和队列服务器&#xff0c;基于…...

论文阅读笔记——双流网络

双流网络论文 视频相比图像包含更多信息&#xff1a;运动信息、时序信息、背景信息等等。 原先处理视频的方法&#xff1a; CNN LSTM&#xff1a;CNN 抽取关键特征&#xff0c;LSTM 做时序逻辑&#xff1b;抽取视频中关键 K 帧输入 CNN 得到图片特征&#xff0c;再输入 LSTM&…...

思路解析:第一性原理解 SQL:连接(JOIN)

目录 题目描述 &#x1f3af; 应用第一性原理来思考这个 SQL 题目 ✅ 第一步&#xff1a;还原每个事件的本质单位 ✅ 第二步&#xff1a;如果一个表只有事件&#xff0c;如何构造事件对&#xff1f; ✅ 第三步&#xff1a;加过滤条件&#xff0c;只保留“同一机器、同一进…...

Java面向对象三大特性深度解析

Java面向对象三大特性封装继承多态深度解析 前言一、封装&#xff1a;数据隐藏与访问控制的艺术1.1 封装的本质与作用1.2 封装的实现方式1.2.1 属性私有化与方法公开化1.2.2 封装的访问修饰符 二、继承&#xff1a;代码复用与类型扩展的核心机制2.1 继承的定义与语法2.2 继承的…...

LabVIEW在电子电工教学中的应用

在电子电工教学领域&#xff0c;传统教学模式面临诸多挑战&#xff0c;如实验设备数量有限、实验过程存在安全隐患、教学内容更新滞后等。LabVIEW 作为一款功能强大的图形化编程软件&#xff0c;为解决这些问题提供了创新思路&#xff0c;在电子电工教学的多个关键环节发挥着重…...

Vue3 怎么在ElMessage消息提示组件中添加自定义icon图标

1、定义icon组件代码&#xff1a; <template><svg :class"svgClass" aria-hidden"true"><use :xlink:href"iconName" :fill"color"/></svg> </template><script> export default defineComponen…...