自定义布局,实现瀑布流效果

自定义流水布局,继承UICollectionViewLayout

实现一下方法


// 每次布局之前的准备
- (void)prepareLayout; // 返回所有的尺寸
- (CGSize)collectionViewContentSize; // 返回indexPath这个位置Item的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath // 返回rect范围内的布局属性
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;

思路:默认有三列,添加图片时,往三列中最大长度最小的那一列添加,

  • 主要工作就在计算最大Y值,然后布局图片

    • 用一个字典用来存储每一列最大的Y值(每一列的高度)

遍历字典找出最短的那一列

 // 找出最短的那一列
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) {
if ([maxY floatValue] < [self.maxYDict[minColumn] floatValue]) {
minColumn = column;
}
}];

服务端返回的数据,必须包含图片的高度和宽度,以此可以根据宽高比布局,根据宽度可以通过代理计算高度。

示例代码
YLCollectionLayout.h
//
// YLCollectionLayout.h
// Created by 邵银岭.
// #import <UIKit/UIKit.h>
@class YLCollectionLayout; @protocol YLCollectionLayoutDelegate <NSObject> - (CGFloat)flowLayout:(YLCollectionLayout *)flowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath; @end @interface YLCollectionLayout : UICollectionViewLayout /** 列间距 */
@property(nonatomic,assign)CGFloat columnMargin;
/** 行间距 */
@property(nonatomic,assign)CGFloat rowMargin;
/** 列数 */
@property(nonatomic,assign)int columnsCount;
/** 外边距 */
@property (nonatomic, assign) UIEdgeInsets sectionInset;
@property (nonatomic, weak) id<YLCollectionLayoutDelegate> delegate;
@end
YLCollectionLayout.m
//
// YLCollectionLayout.m
// Created by 邵银岭
// #import "YLCollectionLayout.h" @interface YLCollectionLayout() /** 这个字典用来存储每一列最大的Y值(每一列的高度) */
@property (nonatomic, strong) NSMutableDictionary *maxYDict;
/** 存放所有的布局属性 */
@property(nonatomic,strong)NSMutableArray *attributeArray;
@end
@implementation YLCollectionLayout - (NSMutableDictionary *)maxYDict
{
if (!_maxYDict) { self.maxYDict = [[NSMutableDictionary alloc] init];
}
return _maxYDict;
} - (NSMutableArray *)attributeArray
{
if (!_attributeArray) {
self.attributeArray = [[NSMutableArray alloc] init];
}
return _attributeArray;
} #pragma mark -初始化默认值
- (instancetype)init
{
if (self = [super init]) {
self.columnMargin = 15;
self.rowMargin = 10;
self.columnsCount = 3;
self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
}
return self;
} - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
} // 布局每一个indexPath的位置
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 1.计算尺寸
CGFloat width = (self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right - (self.columnsCount - 1) * self.columnMargin) / self.columnsCount;
// 代理计算传入高的值
CGFloat height = [self.delegate flowLayout:self heightForWidth:width atIndexPath:indexPath]; // 2.0假设最短的那一列的第0列
__block NSString *minColumn = @"0";
// 遍历字典找出最短的那一列
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) {
if ([maxY floatValue] < [self.maxYDict[minColumn] floatValue]) {
minColumn = column;
}
}]; // 2.1计算位置
CGFloat x = self.sectionInset.left + (self.columnMargin + width) * [minColumn intValue];
CGFloat y = [self.maxYDict[minColumn] floatValue]+ _rowMargin; self.maxYDict[minColumn] = @(y + height);
// 3.创建属性
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attrs.frame = CGRectMake(x, y, width, height);
return attrs;
} - (void)prepareLayout
{
[super prepareLayout];
// 1.清空最大的Y值
for (int i = 0; i<self.columnsCount; i++) {
NSString *column = [NSString stringWithFormat:@"%d", i];
self.maxYDict[column] = @(self.sectionInset.top);
}
[self.attributeArray removeAllObjects]; // 总 item 数
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (int i = 0; i <count; i++) {
UICollectionViewLayoutAttributes *attris = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[self.attributeArray addObject:attris];
} } - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{ return self.attributeArray;
} // 计算ContentSize
- (CGSize)collectionViewContentSize
{
// 默认最大Y值在第0列
__block NSString *maxColumn = @"0";
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) {
if ([maxY floatValue] > [self.maxYDict[maxColumn] floatValue]) {
maxColumn = column;
}
}];
return CGSizeMake(0, [self.maxYDict[maxColumn] floatValue] + self.sectionInset.bottom); }
@end

效果

另一个案例--图片查看器---链接

iOS---UICollectionView自定义流布局实现瀑布流效果的更多相关文章

  1. iOS自定义UICollectionViewLayout之瀑布流

    目标效果 因为系统给我们提供的 UICollectionViewFlowLayout 布局类不能实现瀑布流的效果,如果我们想实现 瀑布流 的效果,需要自定义一个 UICollectionViewLay ...

  2. css基础之 图片瀑布流布局:用CSS+DIV等宽格子堆砌瀑布流效果 (一)

    <!doctype html> <html> <head> <meta charset="UTF-8"/> <title> ...

  3. 自定义UICollectionViewLayout之瀑布流

    目标效果 因为系统给我们提供的 UICollectionViewFlowLayout 布局类不能实现瀑布流的效果,如果我们想实现 瀑布流 的效果,需要自定义一个 UICollectionViewLay ...

  4. RecyclerView实现瀑布流效果(图文详解+源码奉送)

    最近有时间研究了一下RecyclerView,果然功能强大啊,能实现的效果还是比较多的,那么今天给大家介绍一个用RecyclerView实现的瀑布流效果. 先来一张效果图: 看看怎么实现吧: 整体工程 ...

  5. javascript瀑布流效果

    javascript瀑布流效果 其实javascript瀑布流 前几年都已经很流行了(特别是美丽说,蘑菇街),最近看到网上有人问这个瀑布流效果,所以自己有空的时候就研究了下,其实也是研究别人的代码,研 ...

  6. wpf 客户端【JDAgent桌面助手】开发详解(三) 瀑布流效果实现与UI虚拟化优化大数据显示

    目录区域: 业余开发的wpf 客户端终于完工了..晒晒截图 wpf 客户端[JDAgent桌面助手]开发详解-开篇 wpf 客户端[JDAgent桌面助手]详解(一)主窗口 圆形菜单... wpf 客 ...

  7. RecylerView完美实现瀑布流效果

    RecylerView包含三种布局管理器,分别是LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager,对应实现单行列表,多行 ...

  8. 使用JS实现图片展示瀑布流效果

    不知大家有没有发现,一般的图片展示网站都会使用瀑布流效果,所谓的瀑布流 就是网站内的图片不会一下子全缓存出来,而是等你滚动到一定的距离的时候, 下面的图片才会继续缓存,并且图片也是随机出现的,只是宽度 ...

  9. WPF下制作的简单瀑布流效果

    最近又在搞点小东西,美化界面的时候发现瀑布流效果比较不错.顺便就搬到了WPF,下面是界面 我对WEB前端不熟,JS和CSS怎么实现的,我没去研究过,这里就说下WPF的实现思路,相当简单. 1.最重要的 ...

随机推荐

  1. 10601 - Cubes(Ploya)

    UVA 10601 - Cubes 题目链接 题意:给定正方体12条棱的颜色,要求用这些棱能组成多少不同的正方体 思路:利用ploya定理去求解,分类讨论,正方体一共24种旋转.相应的旋转方式有4种: ...

  2. hdu 1251 统计

    他妹的.敲完了.电脑死机了,所有消失了,又从新打了一遍,... 这是什么节奏 #include <stdio.h> #include <string.h> #include & ...

  3. 2016/2/26 <marquee></marquee>实现多种滚动效果

    页面的自动滚动效果,可由javascript来实现,但是有一个html标签 - <marquee></marquee>可以实现多种滚动效果,无需js控制.使用marquee标记 ...

  4. spring依赖注入(反转控制)

    SPRING依赖注入机制(反转控制)解析 Spring能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的 Service对象,还是持久层的DAO对象,都可在Spring的 ...

  5. WIN7 不用格式化磁盘怎么把FAT32系统改成NTFS系统

    开始-运行,输入cmd回车.假设你要转换D盘.输入convert d: /fs:NTFS回车. [ 此时可能会提示: 访问被拒绝 因为你没有足够的特权 是权限不够的原因 开始--程序--附件 右键&q ...

  6. POJO与javabean的区别

    POJO 和JavaBean是我们常见的两个关键字,一般容易混淆,POJO全称是Plain Ordinary Java Object / Pure Old Java Object,中文可以翻译成:普通 ...

  7. O(n²)、O(n)、O(1)、O(nlogn)

    大体上和 @丁戍 说的差不多. 简单说O(n²)表示当n很大的时候,复杂度约等于Cn²,C是某个常数,简单说就是当n足够大的时候,n的线性增长,复杂度将沿平方增长. O(n)也是差不多的意思,也就是说 ...

  8. shinx索引部分源码分析——过程:连接到CSphSource对应的sql数据源,通过fetch row取其中一行,然后解析出field,分词,获得wordhit,最后再加入到CSphSource的Hits里

    CSphSource 数据源 CSphSource_XMLPipe2-XML文件获取数据 CSphSource_SQL-SQL(MySQL)获取数据 CSphIndex 索引器 派生类CSphInde ...

  9. Java 基本类型和对象类型的区别

    Java 基本类型和对象类型的区别 基本类型: int long byte float double char boolean short 对象类型: Integer Long Byte Float ...

  10. SQLite数据库框架--FMDB简单介绍

    1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了很多麻烦.冗余的C语言代码 对比 ...