美文网首页
ios collectionView实现瀑布流

ios collectionView实现瀑布流

作者: 温柔vs先生 | 来源:发表于2023-02-27 14:00 被阅读0次
    1. 重写UICollectionViewLayout
    //
    //  GYYRXCollectionViewLayout.h
    //  GuiYuSiri
    //
    //  Created by wbb on 2023/2/28.
    //
    
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    #define colMargin 10
    #define colCount 2
    #define rolMargin 10
    
    
    @interface GYYRXCollectionViewLayout : UICollectionViewLayout
    
    //数组存放每列的总高度
    @property(nonatomic,strong) NSMutableArray* colsHeight;
    //单元格宽度
    @property(nonatomic,assign) CGFloat colWidth;
    
    
    @property (nonatomic, copy) CGFloat (^heightBlock)(NSIndexPath *indexPath);
    
    - (instancetype)initWithItemsHeightBlock:(CGFloat(^)(NSIndexPath *indexPath))heightBlock;
    
    //完成布局前的初始工作
    -(void)prepareLayout;
    
    //collectionView的内容尺寸
    -(CGSize)collectionViewContentSize;
    
    //为每个item设置属性
    -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
    
    //获取制定范围的所有item的属性
    -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
    
    -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
    @end
    
    NS_ASSUME_NONNULL_END
    
    //
    //  GYYRXCollectionViewLayout.m
    //  GuiYuSiri
    //
    //  Created by wbb on 2023/2/28.
    //
    
    #import "GYYRXCollectionViewLayout.h"
    
    @implementation GYYRXCollectionViewLayout
    
    - (instancetype)initWithItemsHeightBlock:(CGFloat (^)(NSIndexPath * _Nonnull))heightBlock {
          self = [super init];
          if (self) {
              self.heightBlock = heightBlock;
          }
          return self;
    }
    //完成布局前的初始工作
    -(void)prepareLayout{
      [super prepareLayout];
      self.colWidth =( self.collectionView.frame.size.width - (colCount+1)*colMargin )/colCount;
      //让它重新加载
      self.colsHeight = nil;
    }
    //通过遍历colHeight数组里的所有列来获得最长的那一列,返回contentsize
    //collectionView的内容尺寸
    -(CGSize)collectionViewContentSize{
      NSNumber * longest = self.colsHeight[0];
      for (NSInteger i =0;i<self.colsHeight.count;i++) {
        NSNumber* rolHeight = self.colsHeight[i];
        if(longest.floatValue<rolHeight.floatValue){
          longest = rolHeight;
        }
      }
      return CGSizeMake(self.collectionView.frame.size.width, longest.floatValue);
    }
    //为每个item设置属性
    -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
      UICollectionViewLayoutAttributes* attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
      NSNumber * shortest = self.colsHeight[0];
      NSInteger shortCol = 0;
      for (NSInteger i =0;i<self.colsHeight.count;i++) {
        NSNumber* rolHeight = self.colsHeight[i];
        if(shortest.floatValue>rolHeight.floatValue){
          shortest = rolHeight;
          shortCol=i;
        }
      }
      CGFloat x = (shortCol+1)*colMargin+ shortCol * self.colWidth;
      CGFloat y = shortest.floatValue+colMargin;
      
      //获取cell高度
      CGFloat height=0;
      NSAssert(self.heightBlock!=nil, @"未实现计算高度的block ");
      if(self.heightBlock){
        height = self.heightBlock(indexPath);
      }
      attr.frame= CGRectMake(x, y, self.colWidth, height);
      self.colsHeight[shortCol]=@(shortest.floatValue+colMargin+height);
      
      return attr;
    }
    
    //获取所有item的属性
    -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
      NSMutableArray* array = [NSMutableArray array];
      NSInteger items = [self.collectionView numberOfItemsInSection:0];
      for (int i = 0; i<items;i++) {
        UICollectionViewLayoutAttributes* attr = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
        [array addObject:attr];
      }
      return array;
    }
    
    -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
      return YES;
    }
    
    -(NSMutableArray *)colsHeight{
      if(!_colsHeight){
        NSMutableArray * array = [NSMutableArray array];
        for(int i =0;i<colCount;i++){
          //这里可以设置初始高度
          [array addObject:@(0)];
        }
        _colsHeight = [array mutableCopy];
      }
      return _colsHeight;
    }
    @end
    

    使用:

    //
    //  ViewController.m
    //  test
    //
    //  Created by wbb on 2022/12/23.
    //
    
    #import "ViewController.h"
    #import "GYYRXCollectionViewLayout.h"
    
    
    
    @interface ViewController ()<UICollectionViewDelegate, UICollectionViewDataSource>
    
    @property (nonatomic, strong) UICollectionView * collectionView;
    
    @property (nonatomic, copy) NSArray * heightArr;
    @property (nonatomic, strong) UICollectionViewLayout * layout;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        [self initUI];
    }
    
    - (void)initUI {
        
        UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, self.view.frame.size.height) collectionViewLayout:self.layout];
        collectionView.backgroundColor = [UIColor clearColor];
        //5、设置可重用单元格标识与单元格类型
        [collectionView registerClass:NSClassFromString(@"UICollectionViewCell") forCellWithReuseIdentifier:@"UICollectionViewCell"];
        collectionView.showsHorizontalScrollIndicator = NO;
        collectionView.delegate = self;
        collectionView.dataSource = self;
        
        [self.view addSubview:collectionView];
        self.collectionView = collectionView;
    }
    
    #pragma mark collectionView dataSource
    //提供视图中节的个数
    - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
        return 1;
    }
    
    //提供视图中某个节的列数
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
        return 50;//self.dataArr.count; //* _count;
    }
    //为某个单元格提供显示数据
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"UICollectionViewCell" forIndexPath:indexPath];
        
        cell.backgroundColor = [UIColor redColor];
    //    if (indexPath.row < self.dataArr.count) {
    //
    //    }
        return cell;
    }
    //选择单元格后触发
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
        
        
    }
    
    -(UICollectionViewLayout *)layout{
      if(!_layout){
          _layout = [[GYYRXCollectionViewLayout alloc] initWithItemsHeightBlock:^CGFloat(NSIndexPath * _Nonnull indexPath) {
              return [self.heightArr[indexPath.item] floatValue];
          }];
      }
      return _layout;
    }
    -(NSArray *)heightArr{
      if(!_heightArr){
        //随机生成高度
        NSMutableArray *arr = [NSMutableArray array];
        for (int i = 0; i<100; i++) {
          [arr addObject:@(arc4random()%100+100)];
        }
        _heightArr = [arr copy];
      }
      return _heightArr;
    }
    @end
    

    相关文章

      网友评论

          本文标题:ios collectionView实现瀑布流

          本文链接:https://www.haomeiwen.com/subject/lzbhldtx.html