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

自定义流水布局,继承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. .NET的委托和匿名函数应用一例

    闲话休提,大家都是成年人,直接上代码.有代码有J8: delegate string dlgGetTotal(); void TongJi() { dlgGetTotal getTotalInt = ...

  2. js数组清空和去重

    1.splice var ary = [1,2,3,4]; ary.splice(0,ary.length); console.log(ary); // 输出 Array[0],空数组,即被清空了 2 ...

  3. 设计模式-(9)中介者模式(swift)

    在对象去耦合的模式中,有两种模式:中介者模式,观察者模式 一,概念 用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 这个 ...

  4. mondb08---导入导出

    //Mongodb数据的导入导出 : 导入/导出可以操作的是本地的mongodb服务器,也可以是远程的. 所以,都有如下通用选项:(本地机就不用这个了) -h host 主机 --port port ...

  5. c# 字节高低位

    byte n = br.ReadByte(); ; // 高位 var l = n & 0x0f; // 低位

  6. The android gradle plugin version 2.3.0-beta2 is too old, please update to the latest version.

    编译项目的时候,报如下错误: Error:(, ) A problem occurred evaluating project ':app'. > Failed to apply plugin ...

  7. 编译Android VNC Server【转】

    本文转载自:http://www.cnblogs.com/fengfeng/p/3289292.html 1,在如下地址checkout源代码,我checkout的版本为0.9.7http://cod ...

  8. YTU 2596: 编程题B-日期格式

    2596: 编程题B-日期格式 时间限制: 1 Sec  内存限制: 128 MB 提交: 981  解决: 74 题目描述 注:本题只需要提交编写的函数部分的代码即可. 将输入的日期格式 月/日/年 ...

  9. YTU 2800: 逗逗泡泡的保密电文

    2800: 逗逗泡泡的保密电文 时间限制: 1 Sec  内存限制: 128 MB 提交: 229  解决: 114 题目描述 某电报局的电文保密的规律是将每个英文字母变成其后的第4个字母(很原始的那 ...

  10. ubuntu LNMP环境下安装Redis,以及php的redis扩展

    1.下载 sudo wget http://download.redis.io/releases/redis-4.0.9.tar.gz 2.解压 sudo tar zvxf redis-4.0.9.t ...