极客学院Carol老师的UICollectionView实现瀑布流

(1)ViewController.h文件

[objc]  view plain copy
  1. @interface ViewController : UIViewController<UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>  
  2. @property (nonatomicstrongUICollectionView *collectionView;  
  3.   
  4. @end  

ViewController.m文件

[objc]  view plain copy
  1. #import "ViewController.h"  
  2. #import "WaterFallFlowLayout.h"  
  3. #import "WaterFallUICollectionViewCell.h"  
  4. #define WIDTH ([UIScreen mainScreen].bounds.size.width-20)/3  
  5. CGFloat const kImageCount = 16;  
  6. static NSString *identifier = @"collectionView";  
  7. @interface ViewController ()  
  8. @property (nonatomicstrong) NSArray  *imageArr;  
  9. @end  
  10.   
  11. @implementation ViewController  
  12.   
  13. #pragma mark - 图片懒加载  
  14. -(NSArray*)imageArr{  
  15.     if (!_imageArr) {  
  16.         NSMutableArray *muArr = [NSMutableArray array];  
  17.         for (int i=1; i<=kImageCount; i++) {  
  18.             UIImage *image = [UIImage imageNamed:[[NSString alloc] initWithFormat:@"image%d",i]];  
  19.             [muArr addObject:image];  
  20.         }  
  21.         _imageArr = muArr;  
  22.     }  
  23.     return _imageArr;  
  24. }  
  25.   
  26. - (void)viewDidLoad {  
  27.     [super viewDidLoad];  
  28.     WaterFallFlowLayout *flowLayout = [[WaterFallFlowLayout alloc] init];  
  29.     self.collectionView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:flowLayout];  
  30.     self.collectionView.backgroundColor = [UIColor redColor];  
  31.     self.collectionView.delegate = self;  
  32.     self.collectionView.dataSource = self;  
  33.     [self.collectionView registerClass:[WaterFallUICollectionViewCell class] forCellWithReuseIdentifier:identifier];  
  34.     [self.view addSubview:self.collectionView];  
  35. }  
  36.   
  37. #pragma mark - UICollectionView dataSource  
  38. -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{  
  39.     return [self.imageArr count];  
  40. }  
  41.   
  42. -(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{  
  43.     WaterFallUICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];  
  44.     cell.image = self.imageArr[indexPath.item];  
  45.     return cell;  
  46. }  
  47.   
  48. #pragma mark - 计算图片高度  
  49. -(float)imageHeight:(float)height width:(float)width{  
  50.     /* 
  51.      高度/宽度 = 压缩后高度/压缩后宽度 
  52.      */  
  53.     float newHeight = height/width*(WIDTH);  
  54.     return newHeight;  
  55. }  
  56.   
  57. #pragma mark - cell大小  
  58. -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{  
  59.     UIImage *imge = [self.imageArr objectAtIndex:indexPath.row];  
  60.     float height = [self imageHeight:imge.size.height width:imge.size.width];  
  61.     return CGSizeMake(WIDTH, height);  
  62. }  
  63.   
  64. #pragma mark - 边距  
  65. -(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{  
  66.     UIEdgeInsets edgeInsets = {5,5,5,5};  
  67.     return edgeInsets;  
  68. }  
  69.   
  70. @end  


(2)WaterFallFlowLayout.h文件

[objc]  view plain copy
  1. #import <UIKit/UIKit.h>  
  2.   
  3. @interface WaterFallFlowLayout : UICollectionViewFlowLayout  
  4. @property(nonatomic,assign)id<UICollectionViewDelegateFlowLayout> delegate;  
  5. @property(nonatomic,assign)NSInteger cellCount;//cell的个数  
  6. @property(nonatomic,strong)NSMutableArray *colArr;//存放列的高度  
  7. @property(nonatomic,strong)NSMutableDictionary *attributeDict;//cell的位置信息  
  8. @end  


WaterFallFlowLayout.m文件
[objc]  view plain copy
  1. #import "WaterFallFlowLayout.h"  
  2. CGFloat const colCount = 3;  
  3. @implementation WaterFallFlowLayout  
  4. //准备布局:得到cell的总个数,为每个cell确定自己的位置  
  5. - (void)prepareLayout{  
  6.     [super prepareLayout];  
  7.     NSLog(@"prepareLayout");  
  8.     _colArr = [NSMutableArray array];  
  9.     _attributeDict = [NSMutableDictionary dictionary];  
  10.     self.delegate = (id<UICollectionViewDelegateFlowLayout>)self.collectionView.delegate;  
  11.     //获取cell的总个数  
  12.     _cellCount = [self.collectionView numberOfItemsInSection:0];  
  13.     if (_cellCount == 0) {  
  14.         return;  
  15.     }  
  16.     float top = 0;  
  17.     for (int i = 0; i < colCount; i++) {  
  18.         [_colArr addObject:[NSNumber numberWithFloat:top]];  
  19.     }  
  20.     //循环调用layoutForItemAtIndexPath方法,为每个cell布局,将indexPath传入,作为布局字典的key  
  21.     //layoutAttributesForItemAtIndexPath方法的实现,这里用到了一个布局字典,其实就是将每个cell的位置信息与indexPath相对应,将它们放到字典中,方便后面视图的检索  
  22.     for (int i = 0; i < _cellCount; i++) {  
  23.         [self layoutItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];  
  24.     }  
  25.       
  26. }  
  27.   
  28. //此方法会多次调用,为每个cell布局  
  29. - (void)layoutItemAtIndexPath:(NSIndexPath *)indexPath{  
  30.     //通过协议得到cell的间隙  
  31.     NSLog(@"layoutItemAtIndexPath");  
  32.     UIEdgeInsets edgeInsets = [self.delegate collectionView:self.collectionView layout:self insetForSectionAtIndex:indexPath.row];  
  33.     CGSize itemSize = [self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];  
  34.     float col = 0;  
  35.     float shortHeight = [[_colArr objectAtIndex:col] floatValue];  
  36.     //找出高度最小的列,将cell加到最小列中  
  37.     for (int i = 0; i < _colArr.count; i++) {  
  38.         float height = [[_colArr objectAtIndex:i] floatValue];  
  39.         if (height < shortHeight) {  
  40.             shortHeight = height;  
  41.             col = i;  
  42.         }  
  43.     }  
  44.     float top = [[_colArr objectAtIndex:col] floatValue];  
  45.     NSLog(@"top:%f",top);  
  46.     //确定cell的frame  
  47.     CGRect frame = CGRectMake(edgeInsets.left + col * (edgeInsets.left + itemSize.width), top + edgeInsets.top, itemSize.width, itemSize.height);  
  48.     NSLog(@"frme:%f,%f,%f,%f",edgeInsets.left + col * (edgeInsets.left + itemSize.width),top + edgeInsets.top,itemSize.width,itemSize.height);  
  49.     //更新列高  
  50.     [_colArr replaceObjectAtIndex:col withObject:[NSNumber numberWithFloat:top + edgeInsets.top + itemSize.height]];  
  51.       
  52.     //每个cell的frame对应一个indexPath,放入字典中  
  53.     [_attributeDict setObject:indexPath forKey:NSStringFromCGRect(frame)];  
  54. }  
  55.   
  56. - (NSArray *)indexPathsOfItem:(CGRect)rect{  
  57.     //遍历布局字典通过CGRectIntersectsRect方法确定每个cell的rect与传入的rect是否有交集,如果结果为true,则此cell应该显示,将布局字典中对应的indexPath加入数组  
  58.     NSLog(@"indexPathsOfItem");  
  59.     NSMutableArray *array = [NSMutableArray array];  
  60.     for (NSString *rectStr in _attributeDict) {  
  61.         CGRect cellRect = CGRectFromString(rectStr);  
  62.         if (CGRectIntersectsRect(cellRect, rect)) {  
  63.             NSIndexPath *indexPath = _attributeDict[rectStr];  
  64.             [array addObject:indexPath];  
  65.         }  
  66.     }  
  67.     return array;  
  68. }  
  69.   
  70. //返回cell的布局信息,如果忽略传入的rect一次性将所有的cell布局信息返回,图片过多时性能会很差  
  71. - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{  
  72.     NSLog(@"layoutAttributesForElementsInRect");  
  73.     NSMutableArray *muArr = [NSMutableArray array];  
  74.     //indexPathsOfItem方法,根据传入的frame值计算当前应该显示的cell  
  75.     NSArray *indexPaths = [self indexPathsOfItem:rect];  
  76.     for (NSIndexPath *indexPath in indexPaths) {  
  77.       //  UICollectionViewLayoutAttributes *attribute = [self layoutAttributesForItemAtIndexPath:indexPath];  
  78.         UICollectionViewLayoutAttributes *attribute = [self layoutAttributesForItemAtIndexPath:indexPath];  
  79.         [muArr addObject:attribute];  
  80.     }  
  81.     return muArr;  
  82. }  
  83.   
  84. //返回每个CollectionViewCell的属性  
  85. -(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{  
  86.     UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];  
  87.      for (NSString *rectStr in _attributeDict) {  
  88.          if (_attributeDict[rectStr]==indexPath) {  
  89.              attributes.frame = CGRectFromString(rectStr);  
  90.                
  91.          }  
  92.      }  
  93.      return attributes;  
  94. }  
  95.   
  96. //最后还要实现这个方法,返回collectionView内容的大小  
  97. //只需要遍历前面创建的存放列高的数组得到列最高的一个作为高度返回就可以了  
  98. - (CGSize)collectionViewContentSize{  
  99.     NSLog(@"collectionViewContentSize");  
  100.     CGSize size = self.collectionView.frame.size;  
  101.     float maxHeight = [[_colArr objectAtIndex:0] floatValue];  
  102.     //查找最高的列的高度  
  103.     for (int i = 0; i < _colArr.count; i++) {  
  104.         float colHeight = [[_colArr objectAtIndex:i] floatValue];  
  105.         if (colHeight > maxHeight) {  
  106.             maxHeight = colHeight;  
  107.         }  
  108.     }  
  109.     size.height = maxHeight;  
  110.     return size;  
  111. }  
  112. @end  


(3)WaterFallUICollectionViewCell.h文件

[objc]  view plain copy
  1. @interface WaterFallUICollectionViewCell : UICollectionViewCell  
  2. @property(nonatomic,strongUIImage *image;  
  3. @end  

WaterFallUICollectionViewCell.m文件

[objc]  view plain copy
  1. #import "WaterFallUICollectionViewCell.h"  
  2. #define WIDTH ([UIScreen mainScreen].bounds.size.width-20)/3  
  3.   
  4. @implementation WaterFallUICollectionViewCell  
  5. - (void)setImage:(UIImage *)image{  
  6.     if (_image != image) {  
  7.         _image = image;  
  8.     }  
  9.     [self setNeedsDisplay];  
  10. }  
  11. - (void)drawRect:(CGRect)rect{  
  12.     float newHeight = _image.size.height / _image.size.width * WIDTH;  
  13.     [_image drawInRect:CGRectMake(00, WIDTH, newHeight)];  
  14.     self.backgroundColor = [UIColor grayColor];  
  15. }  
  16.   
  17. @end  

(4)运行测试


demo下载地址:http://download.csdn.net/detail/dolacmeng/8682759

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值