1.模型:需要有宽高来控制cell的高度, 


#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface LYBDiscoveryRecomendcollectionviewmodel : NSObject
@property(nonatomic,assign)NSInteger h;
@property(nonatomic,assign)NSInteger w;
@end

NS_ASSUME_NONNULL_END

#import "LYBDiscoveryRecomendcollectionviewmodel.h"

@implementation LYBDiscoveryRecomendcollectionviewmodel

@end

2.

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface LYBDiscoveryRecomandcollectionview : UIView

@end

NS_ASSUME_NONNULL_END

#import "LYBDiscoveryRecomandcollectionview.h"
#import "LYBDiscoveryRecomandWaterFlowLayout.h"
#import "LYBDiscoveryrecommandcollectionviewcell.h"
#import "LYBDiscoveryRecomendcollectionviewmodel.h"
@interface LYBDiscoveryRecomandcollectionview()<UICollectionViewDelegate,UICollectionViewDataSource,LYBDiscoveryRecomandWaterFlowLayoutdelegate>
@property(nonatomic,strong)NSMutableArray *modelarr;
@end
static NSString *const recommandidenfier=@"recommandidenfier";
@implementation LYBDiscoveryRecomandcollectionview
-(NSMutableArray *)modelarr{
    if(nil==_modelarr){
        _modelarr=[[NSMutableArray alloc]init];
    }
    return _modelarr;
}
-(instancetype)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        [self initViews];
        [self initData];
    }
    return self;
}
-(void)initData{
    for (int i=0; i<20; i++) {
        LYBDiscoveryRecomendcollectionviewmodel *model=[[LYBDiscoveryRecomendcollectionviewmodel alloc]init];
        model.h=random()/50+i;
        model.w=random()/50+i;
        [self.modelarr addObject:model];
    }
   
}
-(void)initViews{
    LYBDiscoveryRecomandWaterFlowLayout *flowlayout=[[LYBDiscoveryRecomandWaterFlowLayout alloc]init];
    flowlayout.delegate=self;
    flowlayout.itemSize=CGSizeMake((WIDTH-40*TRANSH)/2,(WIDTH-40*TRANSH)/2);
    UICollectionView *coll=[[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, HEIGHT-BottomHeight-TopSpaceHigh-NAVH*TRANSH) collectionViewLayout:flowlayout];
    [coll registerClass:[LYBDiscoveryrecommandcollectionviewcell class] forCellWithReuseIdentifier:recommandidenfier];
    coll.showsVerticalScrollIndicator=NO;
    coll.backgroundColor=[UIColor whiteColor];
    coll.dataSource=self;
    coll.delegate=self;
    [self addSubview:coll];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return 1;
}
- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return self.modelarr.count;
}
-(__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    LYBDiscoveryrecommandcollectionviewcell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:recommandidenfier forIndexPath:indexPath];
    cell.backgroundColor=[UIColor systemPinkColor];
    return  cell;
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    SLog(@"xuanzhogn");
}


- (CGFloat)LYBDiscoveryRecomandWaterFlowLayout:(LYBDiscoveryRecomandWaterFlowLayout *)LYBDiscoveryRecomandWaterFlowLayout withIndexPath:(NSIndexPath *)indexPath andItemWidth:(CGFloat)width {
    LYBDiscoveryRecomendcollectionviewmodel *model = self.modelarr[indexPath.item];
return width * model.h / model.w;

}

@end

3.自定义flowlayout

#import <UIKit/UIKit.h>
@class LYBDiscoveryRecomandWaterFlowLayout;
NS_ASSUME_NONNULL_BEGIN
@protocol LYBDiscoveryRecomandWaterFlowLayoutdelegate <NSObject>

-(CGFloat)LYBDiscoveryRecomandWaterFlowLayout:(LYBDiscoveryRecomandWaterFlowLayout*)LYBDiscoveryRecomandWaterFlowLayout withIndexPath:(NSIndexPath *)indexPath andItemWidth:(CGFloat)itemWidth;

@end
@interface LYBDiscoveryRecomandWaterFlowLayout : UICollectionViewFlowLayout
@property(nonatomic,weak)id<LYBDiscoveryRecomandWaterFlowLayoutdelegate>delegate;
@end

NS_ASSUME_NONNULL_END

#import "LYBDiscoveryRecomandWaterFlowLayout.h"
@interface LYBDiscoveryRecomandWaterFlowLayout()
// 保存每一列最大的Y值
@property (nonatomic,strong)NSMutableArray *maxYArray;
@end
// 最大列数
static    NSInteger maxColumn =2;
@implementation LYBDiscoveryRecomandWaterFlowLayout
- (NSMutableArray *)maxYArray {
 if (nil ==_maxYArray) {
_maxYArray = [NSMutableArray array];
}
return _maxYArray;
}

-(instancetype)init {
if (self = [super init]) {
}
return self;
}

//准备布局的时候调用 ,当布局刷新(改变)
- (void)prepareLayout {
[super prepareLayout];
}

//当可见范围发生变化的时候, 就会重新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}

#pragma mark -
#pragma mark - 反回的是每一个cell的属性
// 对每一个cell的属性进行设置, frame(x,y,width, height)
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
// 确定最大的列数
//    NSInteger maxColumn = 3;
// 确定行间距, 列间距
 CGFloat columnMargin = 10;
CGFloat rowMargin = 10;
// 确定组的内间距
UIEdgeInsets sectionInsets = UIEdgeInsetsMake(10, 10, 10, 10);
// 取出collectionView 的 size
CGSize collectionViewSize = self.collectionView.frame.size;
// 确定cell 的宽度
CGFloat itemWidth = (collectionViewSize.width - sectionInsets.left - sectionInsets.right - (maxColumn - 1) * columnMargin) / maxColumn;
 // 确定cell的高度

// 取出对应到 indexPath.item , imageArray 的对象
//    ShopModel *shopModel = _imageArray[indexPath.row];
// itemW/itemH = w/h
//    CGFloat itemHeight = itemWidth * shopModel.h / shopModel.w;
 CGFloat itemHeight = [self.delegate LYBDiscoveryRecomandWaterFlowLayout:self withIndexPath:indexPath andItemWidth:itemWidth];
// 确定cell 的 x和  y

// 找到 最短的最大Y值
CGFloat minMaxY = [self.maxYArray[0]doubleValue];
// 定义 最短的列
NSInteger minColumn = 0;
for (int i =1; i <maxColumn; i++) {
// 取出数组中的Y值
CGFloat arrayY = [self.maxYArray[i]doubleValue];
 if (minMaxY > arrayY) {
// 确定最短的最大Y值
minMaxY = arrayY;
 minColumn = i;
}
}

CGFloat itemX = minColumn * itemWidth + minColumn * columnMargin + sectionInsets.left;
CGFloat itemY = minMaxY + rowMargin;
 UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight);
 // 记录 最大Y值
self.maxYArray[minColumn] =@(CGRectGetMaxY(attributes.frame));
 return attributes;
}


#pragma mark -
#pragma mark -  反回可见区域的cell属性
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
// 在每次调用这个方法的时候, 最好把 maxYArray 给清空掉
[self.maxYArray removeAllObjects];
// 对数组做初始化
for (int i =0; i < maxColumn; i++) {
[self.maxYArray addObject:@0];
}
// 实例化一个可变数组
NSMutableArray *itemArray = [NSMutableArray array];
// 取出当前有多少个cell, 反回第0组有多少个cell
NSInteger itemCount = [self.collectionView numberOfItemsInSection:0];
for (int i =0; i < itemCount; i++) {
 // 创建一个 indexPath
 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
// 调用 layoutAttributesForItemAtIndexPath: 返回是对应到indexPath 中cell的属性
UICollectionViewLayoutAttributes *attri = [self layoutAttributesForItemAtIndexPath:indexPath];
// 把cell的属性放到 可变数组中
[itemArray addObject:attri];
 }
return itemArray;
}

- (CGSize)collectionViewContentSize {
    CGFloat maxY = 0;
    if (self.maxYArray.count) {
        maxY = [self.maxYArray[0]doubleValue];
        for (int i =1; i <maxColumn; i++) {
         CGFloat arryY = [self.maxYArray[i]doubleValue];
            if (maxY < arryY) {
             maxY = arryY;
            }
    }
}
return CGSizeMake(0, maxY +10);
}

@end

4.

#import <UIKit/UIKit.h>
#import "LYBDiscoveryRecomendcollectionviewmodel.h"
NS_ASSUME_NONNULL_BEGIN

@interface LYBDiscoveryrecommandcollectionviewcell : UICollectionViewCell
@property(nonatomic,strong)LYBDiscoveryRecomendcollectionviewmodel *model;
@end

NS_ASSUME_NONNULL_END


#import "LYBDiscoveryrecommandcollectionviewcell.h"
@interface LYBDiscoveryrecommandcollectionviewcell()

@end
@implementation LYBDiscoveryrecommandcollectionviewcell
-(instancetype)initWithFrame:(CGRect)frame{
    if(self =[super initWithFrame:frame]){
        [self initviews];
    }
    return self;
}
-(void)initviews{
    self.layer.borderColor=[UIColor blueColor].CGColor;
    self.layer.borderWidth=3;
}

-(void)setModel:(LYBDiscoveryRecomendcollectionviewmodel *)model{
    
}
@end

 

#import "WaterFlowLayout.h"

#import "ShopModel.h"

@interface WaterFlowLayout()

// 保存每一列最大的Y值

@property (nonatomic,strong)NSMutableArray *maxYArray;

@end

// 最大列数

static    NSInteger maxColumn =3;

@implementation WaterFlowLayout

- (NSMutableArray *)maxYArray {

    if (nil ==_maxYArray) {

        _maxYArray = [NSMutableArray array];

    }

    return_maxYArray;

}

- (instancetype)init {

    if (self = [superinit]) {

     }

    return self;

}

//准备布局的时候调用 ,当布局刷新(改变)

- (void)prepareLayout {

    [superprepareLayout];

}

//当可见范围发生变化的时候, 就会重新布局

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {

    returnYES;

}

#pragma mark -

#pragma mark - 反回的是每一个cell的属性

// 对每一个cell的属性进行设置, frame(x,y,width, height)

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {

    // 确定最大的列数

//    NSInteger maxColumn = 3;

// 确定行间距, 列间距

    CGFloat columnMargin = 10;

    CGFloat rowMargin = 10;

// 确定组的内间距

    UIEdgeInsets sectionInsets = UIEdgeInsetsMake(10, 10, 10, 10);

// 取出collectionView 的 size

    CGSize collectionViewSize = self.collectionView.frame.size;

// 确定cell 的宽度

    CGFloat itemWidth = (collectionViewSize.width - sectionInsets.left - sectionInsets.right - (maxColumn - 1) * columnMargin) / maxColumn;

  // 确定cell的高度

#warning 计算cell的高度待定

    // 取出对应到 indexPath.item , imageArray 的对象

//    ShopModel *shopModel = _imageArray[indexPath.row];

    // itemW/itemH = w/h

//    CGFloat itemHeight = itemWidth * shopModel.h / shopModel.w;

  CGFloat itemHeight = [self.delegate waterFlowLayout:self withIndexPath:indexPath andItemWidth:itemWidth];

// 确定cell 的 x和  y

#warning x, y 待计算

  // 找到 最短的最大Y值

    CGFloat minMaxY = [self.maxYArray[0]doubleValue];

   // 定义 最短的列

    NSInteger minColumn = 0;

for (int i =1; i <maxColumn; i++) {

        // 取出数组中的Y值

        CGFloat arrayY = [self.maxYArray[i]doubleValue];

   if (minMaxY > arrayY) {

            // 确定最短的最大Y

            minMaxY = arrayY;

        minColumn = i;

        }

    }

 CGFloat itemX = minColumn * itemWidth + minColumn * columnMargin + sectionInsets.left;

   CGFloat itemY = minMaxY + rowMargin;

  UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

  attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight);

   // 记录 最大Y值

    self.maxYArray[minColumn] =@(CGRectGetMaxY(attributes.frame));

  return attributes;

}

#pragma mark -  反回可见区域的cell属性

- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {

    // 在每次调用这个方法的时候, 最好把 maxYArray 给清空掉

    [self.maxYArray removeAllObjects];

    

    // 对数组做初始化

    for (int i =0; i < maxColumn; i++) {

        [self.maxYArray addObject:@0];

    }

    

    // 实例化一个可变数组

    NSMutableArray *itemArray = [NSMutableArray array];

    

    // 取出当前有多少个cell, 反回第0组有多少个cell

    NSInteger itemCount = [self.collectionView numberOfItemsInSection:0];

  for (int i =0; i < itemCount; i++) {

        // 创建一个 indexPath

        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:iinSection:0];

   // 调用 layoutAttributesForItemAtIndexPath: 返回是对应到indexPath 中cell的属性

        UICollectionViewLayoutAttributes *attri = [self layoutAttributesForItemAtIndexPath:indexPath];

          // 把cell的属性放到 可变数组中

        [itemArray addObject:attri];

    }

    return itemArray;

}

- (CGSize)collectionViewContentSize {

   CGFloat maxY = 0;

  if (self.maxYArray.count) {

        maxY = [self.maxYArray[0]doubleValue];

     for (int i =1; i <maxColumn; i++) {

            CGFloat arryY = [self.maxYArray[i]doubleValue];

           if (maxY < arryY) {

                maxY = arryY;

            }

        }

    }

    return CGSizeMake(0, maxY +10);

}

@end

========================================================
 

#import "ViewController.h"

#import "ShopCell.h"

#import "WaterFlowLayout.h"

#import "ShopModel.h"

@interface ViewController ()<UICollectionViewDataSource,WaterFlowLayoutDelegate>

@property (nonatomic,strong)NSArray *dataArray;

@end

static NSString *identifier =@"shopCell";

@implementation ViewController

#pragma mark -

#pragma mark -  懒加载

- (NSArray *)dataArray {

    if (nil ==_dataArray) {

  //

        NSString *path = [[NSBundle mainBundle]pathForResource:@"shop.plist" ofType:nil];

     //

        NSArray *tempArray = [NSArray arrayWithContentsOfFile:path];

       //

        NSMutableArray *mutable = [NSMutableArray array];

     //

        for (NSDictionary *dictin tempArray) {

            ShopModel *shopModel = [ShopModel shopModelWithDict:dict];

                 [mutable addObject:shopModel];

        }

        _dataArray = mutable;

    }

    return_dataArray;

}

- (void)viewDidLoad {

    [superviewDidLoad];

  // 1. 实例化一个流水布局

    WaterFlowLayout *flowlayout = [[WaterFlowLayout alloc]init];

// 赋值

//    flowlayout.imageArray = self.dataArray;

    flowlayout.delegate = self;

// 2. 实力化一个collectionView

    UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:flowlayout];

  // 3. 设置数据源代理

    collectionView.dataSource = self;

   // 4. 注册一个cell

    UINib *nib = [UINibnibWithNibName:@"ShopCell"bundle:nil];

      [collectionView registerNib:nib forCellWithReuseIdentifier:identifier];

     // 5. collectionView 添加到控制器的view上

    [self.viewaddSubview:collectionView];

}

// 组

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {

    return 1;

}

// 行

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {

    return self.dataArray.count;

}

// 内

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    ShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];

  cell.backgroundColor = [UIColorredColor];

  cell.shopModel = self.dataArray[indexPath.item];

    //cell的contentView的属性是只读的,不能改变,但是可以在contentView上添加子控件

    return cell;

}

#pragma mark -

#pragma mark - 通过代理方法返回 item的高度

- (CGFloat)waterFlowLayout:(WaterFlowLayout *)waterFlowLayout withIndexPath:(NSIndexPath *)indexPath andItemWidth:(CGFloat)width {

    ShopModel *shopModel = self.dataArray[indexPath.item];

     return width * shopModel.h / shopModel.w;

}

@end

 
Logo

更多推荐