iOS 自定义collectionViewLayout 实现瀑布流效果

类似购物平台商品展示的瀑布流效果,通过collectionView实现。需要自己自定义layout。

首先自己创建一个CaCollectionViewLayout 继承于UICollectionViewLayout

.h文件定义属性,方法等:

//总列数
@property (nonatomic, assign) NSInteger columnCount;
//列间距
@property (nonatomic, assign) NSInteger columnSpacing;
//行间距
@property (nonatomic, assign) NSInteger rowSpacing;
//section到collectionView的边距
@property (nonatomic, assign) UIEdgeInsets sectionInset;
//保存每一列最大y值的数组
@property (nonatomic, strong) NSMutableDictionary *maxYDic;
//保存每一个item的attributes的数组
@property (nonatomic, strong) NSMutableArray *attributesArray;
//计算item高度的block,将item的高度与indexPath传递给外界
@property (nonatomic,strong) CGFloat(^itemHeightBlock)(CGFloat itemHeight,NSIndexPath *indexPath);
//设置item间距
- (void)setColumnSpacing:(NSInteger)columnSpacing rowSpacing:(NSInteger)rowSepacing sectionInset:(UIEdgeInsets)sectionInset;
//初始化方法
- (instancetype)initWithColumnCount:(NSInteger)columnCount;

自定义layout需要实现四个方法:

- (void)prepareLayout;
 -(CGSize)collectionViewContentSize;
 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;

直接上代码:

- (void)prepareLayout {
    
     //初始化字典,有几列就有几个键值对,key为列,value为列的最大y值,初始值为上内边距
    for (int i = 0; i obj.floatValue) {
            minIndex = key;
        }
    }];
    //根据最短列的列数计算item的x值
     CGFloat itemX = self.sectionInset.left + (self.columnSpacing + itemWidth) * minIndex.integerValue;
    //item的y值 = 最短列的最大y值 + 行间距
    CGFloat itemY = [self.maxYDic[minIndex] floatValue] + self.rowSpacing;
    
    //设置attributes的frame
    attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight);
    
    //更新字典中的最大y值
    self.maxYDic[minIndex] = @(CGRectGetMaxY(attributes.frame));
    return attributes;
}

//返回rect范围内item的attributes
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    return self.attributesArray;
}

数组和字典记得初始化,此时自定义的布局已经完成。

接下来,我们需要自定义一个CollectionViewCell
重写init方法

- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        //添加自己需要个子视图控件
      
    return self;
}

然后就是使用的时候:

 CaCollectionViewLayout *layout = [[CaCollectionViewLayout alloc]init];
    [layout setColumnSpacing:10 rowSpacing:10 sectionInset:UIEdgeInsetsMake(10, 10, 20, 10)];
    [layout setItemHeightBlock:^CGFloat(CGFloat itemHeight, NSIndexPath *indexPath) {
       //根据图片的原始尺寸,及显示宽度,等比例缩放来计算显示高度
    }];
    self.collectionView = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:layout];
    self.collectionView.backgroundColor = [UIColor whiteColor];
    [self.collectionView registerClass:[myCell class] forCellWithReuseIdentifier:@"layoutCell"];
    self.collectionView.dataSource = self;
    [self.view addSubview:self.collectionView];
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    
    return self.images.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    myCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"layoutCell" forIndexPath:indexPath];
   //在这里对cell中的imageview设置图片 或者在自定义的cell中 重写set方法 设置图片都可以 推荐使用SDWebImage加载图片
    
    return cell;
}

至此,一个简单的瀑布流效果已经完成。

具体可查看Demo

你可能感兴趣的:(iOS 自定义collectionViewLayout 实现瀑布流效果)