自定义 UICollectionViewLayout 布局,实现瀑布流;UICollectionView和UICollectionViewCell 另行创建,这只是布局文件,

外界控制器只要遵守协议并成为他的代理并实现代理方法heightForItemAtIndex:返回每个cell的高就可以实现温布流效果,也

可以实现相应的代理方法设置总共有多少列或是行间距列间距与边框间距。

ViewLayout.h 文件:

#import <UIKit/UIKit.h>
 
@class ViewLayout;
 
@protocol ViewLayoutDelegate <NSObject>
 
// 必须需要实现的代理方法
@required
/** 返回 index 位置的item的高 */
- (CGFloat)viewLayout:(ViewLayout *)ViewLayout heightForItemAtIndex:(NSInteger)index width:(CGFloat)width;
 
// 可选实现的代理方法
@optional
/** 返回 ViewLayout 布局的最大例数代理方法 */
- (CGFloat)numberOfMaxColumnInViewLayout:(ViewLayout *)viewLayout;
 
/** 返回 ViewLayout 布局每列的间距代理方法 */
- (CGFloat)numberOfColumnMarginInViewLayout:(ViewLayout *)viewLayout;
 
/** 返回 ViewLayout 布局的行间距代理方法 */
- (CGFloat)numberOfRowMarginInViewLayout:(ViewLayout *)viewLayout;
 
/** 返回 ViewLayout 布局的上左下右边框间距代理方法 */
- (UIEdgeInsets)edgeInsetsOfEdgeInViewLayout:(ViewLayout *)viewLayout;
 
@end
  
@interface ViewLayout : UICollectionViewLayout
 
/** ViewLayout 代理属性 */
@property (nonatomic, weak) id <ViewLayoutDelegate> delegate;
 
@end

ViewLayout.m 文件:

#import "ViewLayout.h"
 
/** 默认最大例数 */
static const NSInteger defaultMaxColumn = 3;
 
/** 默认例间距 */
static const CGFloat defaultdefaultColumnMargin = 10;
 
/** 默认行间距 */
static const CGFloat defaultdefaultRowMargin = 10;
 
/** 默认边框间距 */
static const UIEdgeInsets defaultEdgeInsets = {10, 10 ,10, 10};
 
@interface ViewLayout ()
 
/** 装有所有的布局性的数组 */
@property (nonatomic, strong) NSMutableArray *attributesArray;
  
/** 装有所有有例的高度 */
@property (nonatomic, strong) NSMutableArray *columnHeights;
 
//方法声明
- (CGFloat)maxColumn;
- (CGFloat)columnMargin;
- (CGFloat)rowMargin;
- (UIEdgeInsets)edgeInsets;
 
@end
  
@implementation ViewLayout
 
/**  返回最大列数 方法实现*/
- (CGFloat)maxColumn{
    if ([self.delegate respondsToSelector:@selector(numberOfMaxColumnInViewLayout:)]) {
        return [self.delegate numberOfMaxColumnInViewLayout:self];
    }else{
        return defaultMaxColumn;
    }
}
 
/** 返回列间距 方法实现*/
- (CGFloat)columnMargin{
    if ([self.delegate respondsToSelector:@selector(numberOfColumnMarginInViewLayout:)]) {
        return [self.delegate numberOfColumnMarginInViewLayout:self];
    }else{
        return defaultdefaultColumnMargin;
    }
}
 
/** 行间距 方法实现*/
- (CGFloat)rowMargin{
    if ([self.delegate respondsToSelector:@selector(numberOfRowMarginInViewLayout:)]) {
        return [self.delegate numberOfRowMarginInViewLayout:self];
    }else{
        return defaultdefaultRowMargin;
    }
}
 
/** 边框的间距 方法实现*/
- (UIEdgeInsets)edgeInsets{
    if ([self.delegate respondsToSelector:@selector(edgeInsetsOfEdgeInViewLayout:)]) {
        return [self.delegate edgeInsetsOfEdgeInViewLayout:self];
    }else{
        return defaultEdgeInsets;
    }
}
 
- (NSMutableArray *)attributesArray{
    if (!_attributesArray) {
        _attributesArray = [NSMutableArray array];
    }
    return _attributesArray;
}
 
- (NSMutableArray *)columnHeights{
    if (!_columnHeights) {
        _columnHeights = [NSMutableArray array];
    }
    return _columnHeights;
}
  
// 准备开始布局时调用方法
- (void)prepareLayout{
 
    [super prepareLayout];
    
    [self.columnHeights removeAllObjects];
    
    [self.attributesArray removeAllObjects];
 
    //先初始给装有所有例高数组赋值
    for (int i = 0; i < self.maxColumn; ++i) {
        self.columnHeights[i] = @(self.edgeInsets.top);
    }
 
    //获取第总共的cell数量
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    
    //有 for循环为每为个 cell添加布局属性
    
    for (int i = 0; i < count; ++i) {
 
        //创建第 i 个位置索引
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        
        //根据索引创建布局属性
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
        
        [self.attributesArray addObject:attributes];
    }
}
 
// 返回所有元素的布局属性数组
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    return self.attributesArray;
}
 
// 返回 索引 indexPath 位置的cell的布属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
    
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    CGFloat width = self.collectionView.bounds.size.width;
 
    CGFloat w = (width - self.edgeInsets.left - self.edgeInsets.right - ((self.maxColumn - 1) * self.columnMargin)) / self.maxColumn;
    
    // 执行代理方法 拿到代理方法返回的高度
    CGFloat h = [self.delegate viewLayout:self heightForItemAtIndex:indexPath.item width:w];
        
    // 找出最短的那一例的高和例号
    CGFloat miniHeight = [self.columnHeights[0] doubleValue]; //先初始默认数组中第0个元素最小值
    NSInteger miniColumn = 0;      //初始默认最小例号
    for (int i = 1; i < self.maxColumn; ++i) {
        CGFloat height = [self.columnHeights[i] doubleValue];
        if (miniHeight > height) {
            miniHeight = height;
            miniColumn = i;
        }
    }
 
    CGFloat x = self.edgeInsets.left + miniColumn * (w + self.columnMargin);
    CGFloat y = miniHeight;
    
    if (y != self.edgeInsets.top) {
        y += self.rowMargin;
    }
    
    attributes.frame = CGRectMake(x, y, w, h);
    //保存更新当前高到对应例的数组
    self.columnHeights[miniColumn] = @(CGRectGetMaxY(attributes.frame));
    return attributes;
}
 
// collectionView的滚动范围
- (CGSize)collectionViewContentSize{
 
    //找出最高的所在例
    CGFloat maxHeight = 0; //初始最大高为 0
    for (int i = 0; i < self.maxColumn; ++i) {
        CGFloat height = [self.columnHeights[i] doubleValue];
        if (maxHeight < height) {
            maxHeight = height;
        }
    }
    return CGSizeMake(0, maxHeight + self.edgeInsets.bottom);
}
@end

自定义UICollectionViewLayout 布局实现瀑布流的更多相关文章

  1. OC - 29.自定义布局实现瀑布流

    概述 瀑布流是电商应用展示商品通常采用的一种方式,如图示例 瀑布流的实现方式,通常有以下几种 通过UITableView实现(不常用) 通过UIScrollView实现(工作量较大) 通过UIColl ...

  2. 自定义基于jquery竖向瀑布流插件

    公司新项目做了一个关于图片的板块,网上找了一些瀑布流插件都不是很适合自己,于是就自己造轮子写一个,并封装成插件github 于是就想分享一下,主要是为了更好的学习与记忆. 如果大家进来了,希望能给我g ...

  3. flex布局实现瀑布流排版

    网上有很多有关js(jq)实现瀑布流和有关瀑布流的插件很多,例如:插件(Masonry,Wookmark等等).按照正常的逻辑思维,瀑布流的排版(item列表)一般都是 由左到右,上而下排序的结果,单 ...

  4. 纯 css column 布局实现瀑布流效果

    原理 CSS property: columns.CSS属性 columns 用来设置元素的列宽和列数. 兼容性 chrome 50+ IE 10+ android browser 2.1+ with ...

  5. 自定义UICollectionViewLayout之瀑布流

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

  6. iOS自定义UICollectionViewLayout之瀑布流

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

  7. iOS 瀑布流之栅格布局

    代码地址如下:http://www.demodashi.com/demo/14760.html 一 .效果预览 二.确定需求 由下面的需求示意图可知模块的最小单位是正方形,边长是屏幕宽除去边距间隔后的 ...

  8. 详解纯css实现瀑布流(multi-column多列及flex布局)

    瀑布流的布局自我感觉还是很吸引人的,最近又看到实现瀑布流这个做法,在这里记录下,特别的,感觉flex布局实现瀑布流还是有点懵的样子,不过现在就可以明白它的原理了 1.multi-column多列布局实 ...

  9. css3多列布局瀑布流加载样式

    看了一些网站的瀑布流加载,正好看到css3的多列属性,尝试着写了一个css做布局的瀑布流. 直接上代码: <!DOCTYPE html> <html lang="en&qu ...

随机推荐

  1. 发运模块中如何创建Debug 文件

     版本11.5.9到12.x A. 针对发运事务处理或者快速发运产生Debug文件 注意:如果通过发运事务处理执行发放,请参考B部分,下面这部分销售订单发放是格外的设置和日志文件. 1.   每一 ...

  2. 百度的android面试总结分析

    今天就是今天上午10点,我接到了百度的电话面试,当然提前和我说了,我的拖延症是有多强烈,以至于我没怎么准备,当然我也想着看看自己的真实水平,在此检讨一下!!!!!!!!!!!!!!!!!!!!!!!! ...

  3. 常用js总结

    通过radio来显示/隐藏一个div <div id="ArbAcei" > <br/> 有无不良反应停药 <input type="rad ...

  4. iOS中 断点下载详解 韩俊强的博客

    布局如下: 基本拖拉属性: #import "ViewController.h" #import "AFNetworking.h" @interface Vie ...

  5. (六十八)使用XMPPFramework登录

    按照XMPPFramework的官方样例,应该把登录代码放置在AppDelegate中,并且让注销成为私有方法. XMPPFramework进行登录的步骤如下: ①连接主机,并且发送JID ②如果连接 ...

  6. iOS模仿京东商城中的选择地区样式

    在ViewController文件中创建添加地址界面: @property(nonatomic,strong)UILabel *selectAreaLabel;//地区显示@property(nona ...

  7. iOS学习新知识-加速计和陀螺仪

    一.CoreMotion框架介绍 我们知道有一些iOS的应用,会有一些特殊的要求,比如: 电子罗盘指南针之类的应用:让我们知道方向. 运动类型软件:让我们知道我们跑步多少公里. 社交软件中的摇一摇功能 ...

  8. shell的case语句

    case语句格式 # vi test.sh : echo "input : " read num echo "the input data is $num" c ...

  9. 开始ITGEGE教育社区的视频录制----嵌入式基础知识讲解

    从8月份开始,陆陆续续要对我的第一份兼职工作ITGEGE讲师做教学视频录制了,本人水平有限,我只讲一些开发在工作中的应用,其它细节的东西不做深究,毕竟本人工作经验和精力也有限,白天要上班,特别是最近又 ...

  10. 【一天一道LeetCode】#67. Add Binary

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given t ...