使用UICollectionView 重写UICollectionViewLayout实现瀑布流
来源:互联网 发布:生死狙击球棒数据变异 编辑:程序博客网 时间:2024/05/10 23:13
实现瀑布流的原理是什么呢 有几个 比较重要的方法 是必须要实现的:
1、 - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds 当collectionView视图位置有新改变(发生移动)时调用,其若返回YES则重新布局
2、 - (void)prepareLayout 准备好布局时调用。此时collectionView所有属性都已确定。我们在这里可以将collectionView当做画布,有了画布后,我们便可以在其上面画出每个item
3、 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 返回collectionView视图中所有视图的属性(UICollectionViewLayoutAttributes)数组
4、 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 返回indexPath对应item的属性
5、- (CGSize)collectionViewContentSize 设置collectionView的可显示范围
其中最主要的方法是3和4俩种方法 ,在3方法中返回所有视图属性数组,并根据这些属性进行布局,而4方法则返回每个item的属性,我们则在这里设置每个item的属性(主要是frame),就可以让collectionView按照我们的意愿进行布局了!(在此我们一半不需要用到1方法,若item属性根据滑动改变,此时就需要随时进行布局改变)
首先 我们在.h文件中 我们需要写一些东西 (列数、行间距、内边距、列间距)
.h
@property(nonatomic, assign)CGFloat lineSpacing; //line space
@property(nonatomic, assign)CGFloat itemSpacing; //item space
@property(nonatomic, assign)CGFloat colCount; //column count
//实现重写flowLayout让代理去完成
@property(nonatomic, weak)id<WaterfallFlowLayoutDelegate> delegate;
//并且 在此处 我们必须要有一个 计算高度的方法,同时这个方法在.m中必须要实现的(这里我使用代理实现,当然也可以使用block)
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterfallFlowLayout *)collectionViewLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath;
//当然如果我们需要添加header和footer 的时候 同样可以声明他的代理方法 例如:
//section header
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterfallFlowLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
//section footer
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(WaterfallFlowLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
接下来 我们在.m中实现方法
- (void)prepareLayout
{
[super prepareLayout];
}
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
- (CGSize)collectionViewContentSize
{
__block NSString * maxCol = @"0";
//遍历找出最高的列
[self.colunMaxYDic enumerateKeysAndObjectsUsingBlock:^(NSString * column, NSNumber *maxY, BOOL *stop) {
if ([maxY floatValue] > [self.colunMaxYDic[maxCol] floatValue]) {
maxCol = column;
}
}];
return CGSizeMake(0, [self.colunMaxYDic[maxCol] floatValue]);
}
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
{
__block NSString * minCol = @"0";
//遍历找出最短的列
[self.colunMaxYDic enumerateKeysAndObjectsUsingBlock:^(NSString * column, NSNumber *maxY, BOOL *stop) {
if ([maxY floatValue] < [self.colunMaxYDic[minCol] floatValue]) {
minCol = column;
}
}];
// 宽度
CGFloat width = (self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right- (self.colCount-1) * self.itemSpacing)/self.colCount;
// 高度
CGFloat height = 0;
if ([self.delegate respondsToSelector:@selector(collectionView:layout:heightForWidth:atIndexPath:)]) {
//
height = [self.delegate collectionView:self.collectionView layout:self heightForWidth:width atIndexPath:indexPath];
}
CGFloat x = self.sectionInset.left + (width + self.itemSpacing) * [minCol intValue];
CGFloat space = 0.0;
if (indexPath.item < self.colCount) {
space = 0.0;
}else{
space = self.lineSpacing;
}
CGFloat y =[self.colunMaxYDic[minCol] floatValue] + space;
// 跟新对应列的高度
self.colunMaxYDic[minCol] = @(y + height);
// 计算位置
UICollectionViewLayoutAttributes * attri = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attri.frame = CGRectMake(x, y, width, height);
return attri;
}
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{
__block NSString * maxCol = @"0";
//遍历找出最高的列
[self.colunMaxYDic enumerateKeysAndObjectsUsingBlock:^(NSString * column, NSNumber *maxY, BOOL *stop) {
if ([maxY floatValue] > [self.colunMaxYDic[maxCol] floatValue]) {
maxCol = column;
}
}];
//header
if ([UICollectionElementKindSectionHeader isEqualToString:elementKind]) {
UICollectionViewLayoutAttributes *attri = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath];
//size
CGSize size = CGSizeZero;
if ([self.delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)]) {
size = [self.delegate collectionView:self.collectionView layout:self referenceSizeForHeaderInSection:indexPath.section];
}
CGFloat x = self.sectionInset.left;
CGFloat y = [[self.colunMaxYDic objectForKey:maxCol] floatValue] + self.sectionInset.top;
// 跟新所有对应列的高度
for(NSString *key in self.colunMaxYDic.allKeys)
{
self.colunMaxYDic[key] = @(y + size.height);
}
attri.frame = CGRectMake(x , y, size.width, size.height);
return attri;
}
//footer
else{
UICollectionViewLayoutAttributes *attri = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:indexPath];
//size
CGSize size = CGSizeZero;
if ([self.delegate respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)]) {
size = [self.delegate collectionView:self.collectionView layout:self referenceSizeForFooterInSection:indexPath.section];
}
CGFloat x = self.sectionInset.left;
CGFloat y = [[self.colunMaxYDic objectForKey:maxCol] floatValue];
// 跟新所有对应列的高度
for(NSString *key in self.colunMaxYDic.allKeys)
{
self.colunMaxYDic[key] = @(y + size.height + self.sectionInset.bottom);
}
attri.frame = CGRectMake(x , y, size.width, size.height);
return attri;
}
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
for(NSInteger i = 0;i < self.colCount; i++)
{
NSString * col = [NSString stringWithFormat:@"%ld",(long)i];
self.colunMaxYDic[col] = @0;
}
NSMutableArray * attrsArray = [NSMutableArray array];
NSInteger section = [self.collectionView numberOfSections];
for (NSInteger i = 0 ; i < section; i++) {
//获取header的UICollectionViewLayoutAttributes
UICollectionViewLayoutAttributes *headerAttrs = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:i]];
[attrsArray addObject:headerAttrs];
//获取item的UICollectionViewLayoutAttributes
NSInteger count = [self.collectionView numberOfItemsInSection:i];
for (NSInteger j = 0; j < count; j++) {
UICollectionViewLayoutAttributes * attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:j inSection:i]];
[attrsArray addObject:attrs];
}
//获取footer的UICollectionViewLayoutAttributes
UICollectionViewLayoutAttributes *footerAttrs = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter atIndexPath:[NSIndexPath indexPathForItem:0 inSection:i]];
[attrsArray addObject:footerAttrs];
}
return attrsArray;
}
到此所有的重写layout 部分就全部完成
接下来 我们只需要在ViewController里面使用即可
ViewController.m中
@interface ViewController ()<WaterfallFlowLayoutDelegate, UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong)UICollectionView *collectionView;
@property (nonatomic, strong)WaterfallFlowLayout *layout;
@end
首先 我们 初始化collectionView 此处必须使用重写后的FlowLayout
self.layout = [WaterfallFlowLayout alloc]init];
self.collectionView = [[UICollectionView alloc]initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:self.layout];
最后加载到视图上面
[self.view addSubview:self.collectionView];
UICollectionView必须要写的俩个方法,同时,此处有一个我们计算每个item大小的代理方法
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(WaterfallFlowLayout*)collectionViewLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath
{
//此处我是是用了一个model类来存储数据的model里面存储了图片等信息,同时 我在model类里面声明了item的宽度和高度
DataModel * model = self.viewModel.dataArray[indexPath.section][indexPath.item];
return model.h / model.w * width;
}
然后 我们在
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
}
此方法里面 我们可以加载每个item 的数据
到此处 一个 较为完整的 瀑布流就布局完成了,如果有什么问题的话 还希望 和每个大神交流探讨,希望大家能过得 开心!!!
- 使用UICollectionView 重写UICollectionViewLayout实现瀑布流
- 自定义UICollectionViewLayout实现瀑布流
- iOS 使用UICollectionView实现瀑布流
- UICollectionView实现瀑布流
- 自定义UICollectionViewLayout—实现瀑布流效果
- iOS自定义UICollectionViewLayout布局实现瀑布流
- UICollectionViewLayout的简单使用(简单瀑布流)
- 瀑布流UICollectionViewFlowLayout/UICollectionViewLayout
- 用UICollectionView实现瀑布流
- UICollectionView的瀑布流实现
- 自定义UICollectionViewLayout之瀑布流
- ios 应用UICollectionView实现瀑布流
- ios 应用UICollectionView实现瀑布流
- iOS UICollectionView实现瀑布流(3)
- 利用UICollectionView 实现 页面瀑布流效果
- iOS UICollectionView实现瀑布流(3)
- UICollectionView瀑布流的实现,带例子
- iOS开发-UICollectionView实现瀑布流
- 5、登录界面布局文件详解
- Aspose Word 导入
- Random类
- eclipse插件项目中的后缀名为.exsd文件的作用
- lintcode:Wood Cut
- 使用UICollectionView 重写UICollectionViewLayout实现瀑布流
- C++索引运算符【】和输出运算符<<重载
- 堆的最大申请数量——我能malloc多少?
- 6、通用类Utils的常用函数
- android之播放视频
- postgresql to_char数字转换
- UART中的硬件流控RTS与CTS
- poj 2965 The Pilots Brothers' refrigerator【枚举】
- MyEclipse 项目部署到tomcat时出现错误之——deploy______http://yang8820.iteye.com/blog/1654466