iOS瀑布流

2023-05-16

WaterFallFlow

瀑布流Demo

瀑布流截图.gif

使用UICollectionView实现瀑布流

自定义UICollectionViewLayout中的主要代码:

YJWaterFlowLayout.h中代码:

#import <UIKit/UIKit.h>
@class YJWaterFlowLayout;

@protocol YJWaterFlowLayoutDelegate <NSObject>
@required
-(CGFloat)waterFlowLayout:(YJWaterFlowLayout *)waterFlowLayout heightForItemAtIndexPath:(NSUInteger)index itemWidth:(CGFloat)itemWidth;

@optional
/** 列数*/
-(CGFloat)columnCountInWaterFlowLayout:(YJWaterFlowLayout *)waterFlowLayout;
/** 列间距*/
-(CGFloat)columnMarginInWaterFlowLayout:(YJWaterFlowLayout *)waterFlowLayout;
/** 行间距*/
-(CGFloat)rowMarginInWaterFlowLayout:(YJWaterFlowLayout *)waterFlowLayout;
/** 边缘之间的间距*/
-(UIEdgeInsets)edgeInsetInWaterFlowLayout:(YJWaterFlowLayout *)waterFlowLayout;

@end

@interface YJWaterFlowLayout : UICollectionViewLayout

/** delegate*/
@property (nonatomic, weak) id<YJWaterFlowLayoutDelegate> delegate;

@end

YJWaterFlowLayout.m文件代码:


#import "YJWaterFlowLayout.h"
/** 默认的列数*/
static const NSInteger YJDefaultColumeCount = 3;
/** 每一列之间的间距*/
static const NSInteger YJDefaultColumeMargin = 10;
/** 每一行之间的间距*/
static const CGFloat YJDefaultRowMargin = 10;
/** 边缘之间的间距*/
static const UIEdgeInsets YJDefaultEdgeInset = {10, 10, 10, 10};

@interface YJWaterFlowLayout ()
/** 存放所有cell的布局属性*/
@property (strong, nonatomic) NSMutableArray *attrsArray;
/** 存放每一列的最大y值*/
@property (nonatomic, strong) NSMutableArray *columnHeights;
/** 每一行之间的间距*/
-(CGFloat)rowMargin;
/** 每一列之间的间距*/
-(CGFloat)columnMargin;
/** 列数*/
-(NSInteger)columnCount;
/** 边缘之间的间距*/
-(UIEdgeInsets)edgeInsets;

/** 内容的高度*/
@property (nonatomic, assign) CGFloat maxColumnHeight;

@end

@implementation YJWaterFlowLayout

#pragma mark 代理方法处理
-(CGFloat)rowMargin {
    if ([self.delegate respondsToSelector:@selector(rowMarginInWaterFlowLayout:)]) {
       return [self.delegate rowMarginInWaterFlowLayout:self];
    } else {
        return YJDefaultRowMargin;
    }
}

-(CGFloat)columnMargin {
    if ([self.delegate respondsToSelector:@selector(columnMarginInWaterFlowLayout:)]) {
        return [self.delegate columnMarginInWaterFlowLayout:self];
    } else {
        return YJDefaultColumeMargin;
    }
}

-(NSInteger)columnCount {
    if ([self.delegate respondsToSelector:@selector(columnCountInWaterFlowLayout:)]) {
        return [self.delegate columnCountInWaterFlowLayout:self];
    } else {
        return YJDefaultColumeCount;
    }
}

-(UIEdgeInsets)edgeInsets {
    if ([self.delegate respondsToSelector:@selector(edgeInsetInWaterFlowLayout:)]) {
        return [self.delegate edgeInsetInWaterFlowLayout:self];
    } else {
        return YJDefaultEdgeInset;
    }
}

#pragma mark - 懒加载
- (NSMutableArray *)columnHeights {
    if (!_columnHeights) {
        _columnHeights = [NSMutableArray array];
    }
    return _columnHeights;
}

-(NSMutableArray *)attrsArray {
    if (_attrsArray == nil) {
        _attrsArray = [NSMutableArray array];
    }
    return _attrsArray;
}

/** 初始化*/
-(void)prepareLayout {
    [super prepareLayout];

    //清除以前计算的所有高度
    self.maxColumnHeight = 0;
    [self.columnHeights removeAllObjects];
    for (NSInteger i = 0; i < self.columnCount; i++) {
        [self.columnHeights addObject:@(self.edgeInsets.top)];
    }

    //清除之前数组
    [self.attrsArray removeAllObjects];

    //开始创建每一个cell
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    for (NSInteger i = 0; i < count; i++) {
        //创建位置
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        //获取indexPath位置cell对应的成员属性
        UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
        [self.attrsArray addObject:attrs];
    }
}

/** 决定cell的排布*/
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    return self.attrsArray;
}

/** 返回indexPath位置cell对应的布局属性*/
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    //设置布局属性
    UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes  layoutAttributesForCellWithIndexPath:indexPath];
    //collectionView的宽度
    CGFloat collectionW = self.collectionView.frame.size.width;
    //设置布局属性的frame
    CGFloat w = (collectionW - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
    CGFloat h = [self.delegate waterFlowLayout:self heightForItemAtIndexPath:indexPath.item itemWidth:w];

    //找出高度最短的那一列
    NSInteger destColumn = 0;
    CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];
    for (NSInteger i = 1; i < self.columnCount; i++) {
        //取出第i列
        CGFloat columnHeight = [self.columnHeights[i] doubleValue];
        if (minColumnHeight > columnHeight) {
            minColumnHeight = columnHeight;
            destColumn = i;
        }
    }

    CGFloat x = self.edgeInsets.left + destColumn * (w + self.rowMargin);
    CGFloat y = minColumnHeight;
    if (y != self.edgeInsets.top) {
        if ([self.delegate respondsToSelector:@selector(rowMarginInWaterFlowLayout:)]) {
            y += [self.delegate rowMarginInWaterFlowLayout:self];
        } else {
            y += self.rowMargin;
        }
    }

    attrs.frame = CGRectMake(x, y, w, h);
    //更新最短那列的高度
    self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));
    //记录内容的高度
    CGFloat columnHeight = [self.columnHeights[destColumn] doubleValue];
    if (self.maxColumnHeight < columnHeight) {
        self.maxColumnHeight = columnHeight;
    }

    return attrs;
}


-(CGSize)collectionViewContentSize {
    return CGSizeMake(0, self.maxColumnHeight + self.edgeInsets.bottom);
}

@end

瀑布流Demo地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS瀑布流 的相关文章

  • iOS高德地图路径选择

    新公司的一个物流项目用到了高德地图的路径规划导航 之前没用过高德的路径规划 xff0c 最麻烦的是画出路径 xff0c 以及多路径情况下的点击选择路径 其实画出路径的算法在高德地图的相关demo里面有 xff0c 只要抠出来就行 我要说的是
  • 今日解决新安装的centos 8安装MYSQL提示未找到匹配的参数: mysql-community-server

    今日新安装的centos在安装mysql community server时一直报错 xff1a root 64 centos8 yum repos d yum y install mysql community server 上次元数据过
  • ios学习--给UITableViewCell动态调整高度

    在网上看到有人如此实现动态调整高度 xff1a 点击 不至于为了获取高度创建一个不需要的cell 主要有两个地方需要调整高度 xff0c 一个是自己创建的UILabel或其它 xff0c 另一个就是cell的高度 在创建cell的地方只需要
  • 【HTML5】-04 图片与链接

    图片与链接 xff1a lt DOCTYPE html gt lt html gt lt head gt lt title gt 第二页 lt title gt lt head gt lt body gt lt p gt 1 图片插入 xf
  • lanzous.com网站无法访问求解决

    一般的分享链接是https XXXXX lanzous com sssss 直接把前面的https XXXXX lanzous com改成https pan lanzou com就行 最后链接样式就是https pan lanzous co
  • C++风格_格式

    1 行长度 每一行代码字符数不超过 80 xff08 这个数是Google的指南中的 xff09 80 个字符是最大值 如果无法在不伤害易读性的条件下进行断行 那么注释行可以超过 80 个字符 这样可以方便复制粘贴 例如 带有命令示例或 U
  • TCP Server处理多Client请求的方法—非阻塞accept与select

    参看基于TCP UDP的socket代码 xff0c 同一时间Server只能处理一个Client请求 xff1a 在使用当前连接的socket和client进行交互的时候 xff0c 不能够accept新的连接请求 为了使Server能够
  • jupyter notebook下识别出虚拟环境

    在需要的虚拟环境里安装 conda span class token function install span c conda forge ipykernel 这样启动jupyter notebook就可以看到了 也可以在安装虚拟环境时就
  • VMware Ubuntu20.04设置共享文件夹

    虚拟机设置好共享文件夹后进入系统可能会找不到 xff0c 这时需要经过如下操作才能在系统中看到 vmware hgfsclient 可以在Terminal里显示出已经设置好的共享文件夹 span class token function s
  • Vim技巧-多行缩进

    向前或向后缩进4个空格 按shift 43 v组合键进入Visual Line模式 xff0c 可使用方向键选择多行 xff1b 按 lt 或 gt xff0c 进行向前或向后缩进 注 xff1a 有些设置为缩进一个Tab单位 向前或向后缩
  • nginx 配置git server http clone服务,并通过反向代理访问

    要做一个通过踏板机的ip进行git代码的上传与下载 xff0c 所以思路不是踏板机上安装nginx反向代理 xff0c 并且linux服务器也需要提供http方式的访问git xff0c ssh方向不知道怎么进行反向代理 linux服务器也
  • ESP8266 Windows开发环境搭建(IDE1.5)好用不骗人

    最近一个项目需要用ESP8266 xff0c 找了很多文章进行环境搭建编译都很问题 xff0c 不是make Menuconfig 不出来 xff0c 就是编译报错 xff0c 现总结如下 我在自己电脑上没弄出来 xff0c 就安装了一个虚
  • React-Native run-android报错以及adb 命令不识别

    在遇到adb 命令不识别 xff0c 或者genymotion的模拟器不识别 xff0c 找不到的问题 都是genymotion配置的不正确 打开genymotion的adb设置 xff0c androidSDK的配置选择自己下载的andr
  • android 浏览器 打开本地html文件的方法

    android 浏览器 打开本地html文件的方法有些html文件放在本地磁盘和sdcard xff0c 如何用打开这个网页呢 xff1f 这种应用在测试时非常有用 有 xff12 个方法 xff1a xff11 使用文件管理器 如ES等
  • 中国各主要大城市经纬度数据

    lt p gt 1 中国各主要大城市经纬度数据 xff1a lt br gt 北京市市中心经纬度 116 41667 39 91667 lt br gt 上海市区经纬度 121 43333 34 50000 lt br gt 天津市区经纬度
  • C# 中关闭当前线程的四种方式

    net类库已经帮助我们实现了窗口的关闭 xff0c 如果此窗口是系统的主窗口 xff0c 关闭此窗口即应该退出了整个应用程序 但事实上有时候并不是这样的 xff0c 关闭窗口 xff0c 只是停止了当前窗口的消息循环 系统主窗口 xff0c
  • linux+live555搭建rtsp服务器

    linux 43 live555搭建rtsp服务器 下载并解压接下来生成Make文件 xff0c 生成需要的文件在live文件夹下make之后会在当前目录下生成mediaServer 文件夹 xff0c 其中有一个live555MediaS
  • Navicat for SQLite 15中文版

    教程 xff1a 1 下载软件压缩包并且解压文件获得安装文件以及文件 2 双击exe文件开始安装并且选择同意用户协议 3 选择软件安装位置 4 软件安装读条中请耐心等待 5 软件安装完成 xff0c 资源地址 xff1a Navicat f
  • ascs 简明开发教程(十八):定时器

    QQ交流群 xff1a 198941541 前面讲过 xff0c ascs支持定时器 xff08 由asio实现 xff09 xff0c socket和object pool都继承自timer对象 xff0c 所以你几乎可以在任意地方使用定
  • 向MySQL数据库中存入json类型数据

    源文章地址 xff1a https www linuxidc com Linux 2017 03 141865 htm 0 说明 因为出于个人项目的需要 xff0c 获取到的数据都是json类型的 xff0c 并且都要存入MySQL数据库中

随机推荐

  • win10安装ElasticSearch,启动闪退问题

    JDK环境原因 xff0c 重新安装一下 xff0c 问题解决
  • JWT生成私钥和公钥

    JWT令牌生成采用非对称加密算法 1 生成密钥证书 下边命令生成密钥证书 xff0c 采用RSA 算法每个证书包含公钥和私钥 keytool genkeypair alias xckey keyalg RSA keypass xuechen
  • 浏览器中Local Storage和Session Storage的区别

    Local Storage xff1a 数量空间没有限制 xff0c 只要硬盘空间较大 xff0c 可以一直存 Session Storage xff1a 是一个会话存储对象 xff0c 在Session Storage中保存的数据只能在同
  • win10 MongoDB启动失败 Error: couldn't connect to server 127.0.0.1:27017, connection attempt faile

    1 我的MongoDB安装路径 2 创建配置文件mongo conf xff0c 文件内容如下 xff1a 数据库路径 dbpath 61 d MongoDB Server 3 4 data 日志输出文件路径 logpath 61 d Mo
  • "docker build"requires exactly 1 argument

    例如运行 xff1a docker build t xc govern center 1 0 SNAPSHOT 后面的这个 前面是有个空格的
  • PyCharm 快捷键

    ctrl 43 alt 43 s xff1a 打开软件设置 ctrl 43 d xff1a 复制当前行代码 shift 43 alt 43 上 下 xff1a 将当前行代码上移或下移 ctrl 43 shift 43 f10 xff1a 运
  • Python进阶

    1 Ubuntu操作系统 Linux主要目录 xff1a xff1a 根目录 bin xff1a 可执行二进制文件的目录 ect xff1a 系统配置文件存放的目录 home xff1a 用户家目录 2 linux命令 查看目录命令 命令说
  • Python+tkinter应用程序设置背景图片

    功能描述 xff1a 设计tkinter应用程序 xff0c 为窗口和组件设置背景图片 参考代码 xff1a 运行效果 xff1a 董付国老师Python系列图书 友情提示 xff1a 不建议购买太多 xff0c 最好先通过京东 当当 天猫
  • git学习

    1 git和svn的区别 svn是集中式版本控制系统 xff0c 版本库是集中放在中央服务器的 xff0c 而工作的时候 xff0c 用的都是自己的电脑 xff0c 所以首先要从中央服务器得到最新的版本 xff0c 然后工作 xff0c 完
  • git常用命令

    1 git下载完后 xff0c 必须要设置签名 xff0c 否则无法提交代码 2 C Users 12131 gitconfig 文件里可以查看到设置的信息 3 签名的作用 xff1a 区分不同操作者身份 xff0c 用户的签名信息在每一个
  • GitHub上 README 增加图片标签

    hey Guys 你可能遇到的GitHub上好的项目都有一个非常棒的README xff0c 其中不乏用到一些非常好看的标签 比如下面这样 xff1a walle fastjson 那我们怎样自己添加一个高大上图片标签呢 xff1f 比如我
  • 树莓派上使用 Gstreamer做视频推流

    树莓派使用Gstreamer进行视频推流 最近在研究如何使用树莓派进行视频推流推送到云端 进行了各种比较尝试后 xff0c 认为使用Gstreamer比较好 xff0c 主要的一点就是想利用Gstreamer的硬件加速 在使用ffmpeg的
  • geoserver jms集群部署

    1 集群节点运行架构图 官网集群介绍 xff1a https docs geoserver org latest en user community jms cluster index html 节点之间通过jms消息通信 xff0c A节
  • linux smb配置 不修改git权限

    root 64 localhost cat etc samba smb conf map archive 61 no map hidden 61 no map read only 61 no map system 61 no store d
  • luogu P1185 绘制二叉树

    题目大意 绘制一棵给定的二叉树 解题思路 模拟即可 代码比较乱 include lt cstdio gt include lt cstdlib gt include lt cstring gt const int MAXN 61 12 第i
  • shell 自动化运维

    1 shell 基础知识 1 shell是一个程序 xff0c 文件路径 xff1a bin bash xff0c 是一个命令解释器 xff0c 所有的linux命令都由它来执行 打开终端 xff0c 就进入了shell交互式命令 2 sh
  • 递归求鸭子数

    一个人赶着鸭子去每个村庄卖 xff0c 每经过一个村子卖去所赶鸭子的一半又一只 这样他经过了七个村子后还剩两只鸭子 xff0c 问他出发时共赶多少只鸭子 xff1f 经过每个村子卖出多少只鸭子 xff1f span style color
  • 【STM32】基于STM32F407寄存器方式点亮LED流水灯

    目录 一 STM32F4寄存器介绍二 通过寄存器方式点亮流水灯1 硬件设计2 软件设计3 烧录验证 三 原理阐述1 使能IO口时钟2 初始化IO口模式3 操作IO口 xff0c 输出高低电平 四 总结五 参考 本文使用 原子STM32F40
  • Python+tkinter+pillow实现屏幕任意区域截图

    基本思路 xff1a 首先获取并显示全屏幕截图 xff0c 然后在全屏幕截图上响应鼠标左键按下和抬起事件 xff0c 最后进行二次截图 import tkinter import tkinter filedialog import os f
  • iOS瀑布流

    WaterFallFlow 瀑布流Demo 使用UICollectionView实现瀑布流 自定义UICollectionViewLayout中的主要代码 xff1a YJWaterFlowLayout h中代码 span class hl