简单瀑布流的实现

简单瀑布流的实现

最近在开发公司的项目里,有一条需求是需要瀑布流的方法实现,之前指写过简单的collectionView 。没有写过变化的集合视图。于是研究了一下简单的瀑布流实现方法

实现瀑布流主要是重写了UICollectionViewLayout的几个方法

1.-(void)prepareLayout
2.- (CGSize)collectionViewContentSize
3.- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
4.- (UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath

第一个方法是做一些初始化的操作,这个方法必须先调用一下父类的实现
第二个方法 返回UICollectionView 的可滚动范围
第三个方法返回 可视范围 UICollectionViewLayoutAttributes 属性的数组
第四个方法是返回indexPath位置UICollectionViewLayoutAttributes属性

我们首先要明白的是瀑布流的排列,瀑布流是把长短不一的控件排列在手机屏幕上,我们排完第一列的时候就会依次往下面排,怎么拍呢。答案是排在第一列最短的那个控件下面,以此类推,然后以此排下去。明白这一点,我们直接上代码

typedef CGFloat(^HeightBlock) (NSIndexPath *indexPath , CGFloat width);

@interface WYCollectionLayout : UICollectionViewLayout

/**
列数
*/
@property(nonatomic,assign) NSInteger lineNumber;

/**
行间距
*/
@property(nonatomic,assign) CGFloat rowSpacing;

/**
列间距
*/
@property(nonatomic,assign) CGFloat lineSpacing;

/**
内边距
*/
@property(nonatomic,assign) UIEdgeInsets sectionInset;

/**
对象方法

@param block 在block中最后要返回一个item的高度
*/
-(void)computeIndexCellHeightWithWidthBlock:(CGFloat(^)(NSIndexPath *indexPath , CGFloat width))block;

@interface WYCollectionLayout()

/**
存放每列高度的字典
*/
@property(nonatomic,strong)NSMutableDictionary *dicOfheight;

/**
存放所有item的attribute属性
*/
@property(nonatomic,strong)NSMutableArray *array;

/**
计算每个item高度的block,必须实现
*/
@property(nonatomic,copy)HeightBlock block;

@end

@implementation WYCollectionLayout

  • (instancetype)init {

    self = [super init];
    if (self) {

    //对默认属性进行设置
    //默认行数 2行
    //默认行间距 10.0f
    //默认列间距 10.0f
    //默认内边距 top:10 left:10 bottom:10 right:10
    
    self.lineNumber = 2;
    self.rowSpacing = 10.0f;
    self.lineSpacing = 10.0f;
    self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
    _dicOfheight = [NSMutableDictionary dictionary];
    _array = [NSMutableArray array];
    

    }
    return self;
    }

/**
* 准备好布局时调用
*/
- (void)prepareLayout {

[super prepareLayout];
NSInteger count = [self.collectionView numberOfItemsInSection:0];
//初始化好每列的高度
for (NSInteger i = 0; i < self.lineNumber ; i++) {

    [_dicOfheight setObject:@(self.sectionInset.top) forKey:[NSString stringWithFormat:@"%ld",i]];

}
//得到每个item的属性值进行存储
for (NSInteger i = 0 ; i < count; i ++) {

    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
    [_array addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];

}

}

/**
* 设置可滚动区域范围
*
* @return 可滚动区域的size
*/
- (CGSize)collectionViewContentSize {

__block NSString *maxHeightline = @"0";
[_dicOfheight enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *obj, BOOL *stop) {

    if ([_dicOfheight[maxHeightline] floatValue] < [obj floatValue] ) {
        maxHeightline = key;
    }
}];
return CGSizeMake(self.collectionView.bounds.size.width, [_dicOfheight[maxHeightline] floatValue] + self.sectionInset.bottom);

}

/**
*return 返回视图框内item的属性,可以直接返回所有item属性
*/
- (NSArray)layoutAttributesForElementsInRect:(CGRect)rect {

return _array;

}

/**
* 计算indexPath下item的属性的方法
*
* @return item的属性
*/
- (UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath {

UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//计算item宽
CGFloat itemW = (self.collectionView.bounds.size.width - (self.sectionInset.left + self.sectionInset.right) - (self.lineNumber - 1) * self.lineSpacing) / self.lineNumber;
CGFloat itemH;
//计算item高
if (self.block != nil) {

    itemH = self.block(indexPath, itemW);
}else {
    NSAssert(itemH != 0,@"Please implement computeIndexCellHeightWithWidthBlock Method");
}
//计算item的frame
CGRect frame;
frame.size = CGSizeMake(itemW, itemH);
//循环遍历找出高度最短行
__block NSString *lineMinHeight = @"0";
[_dicOfheight enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *obj, BOOL *stop) {
    if ([_dicOfheight[lineMinHeight] floatValue] > [obj floatValue]) {
        lineMinHeight = key;
    }
}];
int line = [lineMinHeight intValue];
//找出最短行后,计算item位置
frame.origin = CGPointMake(self.sectionInset.left + line * (itemW + self.lineSpacing), [_dicOfheight[lineMinHeight] floatValue]);
_dicOfheight[lineMinHeight] = @(frame.size.height + self.rowSpacing + [_dicOfheight[lineMinHeight] floatValue]);
attr.frame = frame;

return attr;

}

/**
* 设置计算高度block方法
*
* @param block 计算item高度的block
*/
- (void)computeIndexCellHeightWithWidthBlock:(CGFloat (^)(NSIndexPath *, CGFloat))block {

if (self.block != block) {

    self.block = block;
}

}

Demo地址:https://github.com/tomBob/pubuliu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值