• 自定义UICollectionViewLayout(适用于多个section)


    一、自定义layout主要方法

      重写系统的- (void)prepareLayout  方法;

      其实就是计算每个cell的frame和其它相关属性。

      

     二、在网上看了好多自定义的layout 但是没有多section的,就整了这个……

      全部代码:

    .h文件
    @class ForeverGuardFlowLayout;
    @protocol ForeverGuardFlowLayoutDelegate <NSObject>
    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(ForeverGuardFlowLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
    @end
    
    @interface ForeverGuardFlowLayout : UICollectionViewFlowLayout
    
    @property(nonatomic, assign)NSUInteger numberOfColumn;//列数
    @property(nonatomic, assign)id<ForeverGuardFlowLayoutDelegate>delegate;
    
    @end

      

      1 @interface ForeverGuardFlowLayout()
      2 //存放每一列的高度
      3 @property (nonatomic, retain) NSMutableArray *columnHeightsArray;
      4 
      5 //每个section的每一列的高度
      6 @property (nonatomic, retain) NSMutableArray *collectionHeightsArray;
      7 
      8 //存放每一个cell的属性
      9 @property (nonatomic, retain) NSMutableArray *attributesArray;
     10 
     11 
     12 @end
     13 @implementation  ForeverGuardFlowLayout
     14 
     15 
     16 /**
     17  每个区的最小高度
     18 
     19  @param section 区索引
     20  @return 高度
     21  */
     22 - (CGFloat)minHeightWithSection:(NSInteger)section{
     23     CGFloat min = 1000000;
     24     for (NSNumber *height in _collectionHeightsArray[section]) {
     25         if (min > [height floatValue]) {
     26             min = [height floatValue];
     27         }
     28     }
     29     return min;
     30 }
     31 
     32 
     33 /**
     34  每个区的初始Y坐标
     35 
     36  @param section 区索引
     37  @return Y坐标
     38  */
     39 - (CGFloat)maxHeightWithSection:(NSInteger)section{
     40     
     41     if (section>0) {
     42         CGFloat max = 0;
     43         for (int i=0; i<section; i++) {
     44             max += [self maxHeightAboutSection:_collectionHeightsArray[i]];
     45         }
     46         return max;
     47     }else{
     48         return 0;
     49     }
     50     
     51 }
     52 
     53 
     54 /**
     55  每个区的最大高度
     56 
     57  @param dataArr 每个区的所有列的高度
     58  @return 最大高度
     59  */
     60 - (CGFloat)maxHeightAboutSection:(NSMutableArray *)dataArr{
     61     CGFloat max = 0;
     62     for (NSNumber *heigth  in dataArr) {
     63         if (max < [heigth floatValue]) {
     64             max = [heigth floatValue];
     65         }
     66     }
     67     return max;
     68 
     69 }
     70 
     71 
     72 /**
     73  collectionView的显示高度
     74  */
     75 - (CGFloat)collectionHeight{
     76     CGFloat max = 0;
     77     for (NSMutableArray *sectionArr in _collectionHeightsArray) {
     78         max += [self maxHeightAboutSection:sectionArr];
     79     }
     80     return max;
     81 }
     82 
     83 
     84 /**
     85  当前区的最小高度的索引
     86 
     87  @param section 当前区
     88  @return 最小高度的索引
     89  */
     90 - (NSUInteger)indexOfMinHeightWithSection:(NSInteger)section{
     91     NSUInteger index  = 0;
     92     NSMutableArray *sectionArr = _collectionHeightsArray[section];
     93     for (int i=0; i<sectionArr.count; i++) {
     94         CGFloat height = [sectionArr[i] floatValue];
     95         if (height == [self minHeightWithSection:section]) {
     96             index = i;
     97             return index;
     98         }
     99     }
    100     return index;
    101 }
    102 
    103 
    104 /**
    105  重写系统prepareLayout方法 (设置item的坐标等属性)
    106  */
    107 - (void)prepareLayout{
    108     [super prepareLayout];
    109     
    110     _attributesArray = [[NSMutableArray alloc] init];
    111     
    112     _columnHeightsArray = [NSMutableArray arrayWithCapacity:self.numberOfColumn];
    113     
    114     NSUInteger sectionCount = [self.collectionView numberOfSections];
    115     _collectionHeightsArray = [NSMutableArray arrayWithCapacity:sectionCount];
    116     
    117     for (int index = 0; index<sectionCount; index++) {
    118         NSMutableArray *columnArr = [NSMutableArray array];
    119         for (int i=0; i<self.numberOfColumn; i++) {
    120             [columnArr addObject:@0.0];
    121         }
    122         [_collectionHeightsArray addObject:columnArr];
    123     }
    124     
    125     CGFloat totalWidth = self.collectionView.frame.size.width;
    126     
    127     CGFloat x = 0;
    128     CGFloat y = 0;
    129     
    130     for (int index= 0; index<sectionCount; index++) {
    131         NSUInteger  itemCount = [self.collectionView numberOfItemsInSection:index];
    132         x = 0;
    133         y = [self maxHeightWithSection:index];
    134         for (int i=0; i<itemCount; i++) {
    135             NSUInteger numberIfSoace = self.numberOfColumn-1;
    136             CGFloat spaceWidth = 7.5;//item左右间距
    137             CGFloat width = (totalWidth - spaceWidth*numberIfSoace)/self.numberOfColumn;
    138             
    139             NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:index];
    140             
    141             CGSize imageSize =[self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
    142             
    143             CGFloat height = width * imageSize.height / imageSize.width;
    144             
    145             UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    146             
    147             attributes.frame = CGRectMake(x, y, width, height);
    148             [_attributesArray addObject:attributes];
    149             
    150             
    151             NSUInteger minHeightIndex = [self indexOfMinHeightWithSection:index];
    152             
    153             CGFloat minHeight = [_collectionHeightsArray[index][minHeightIndex] floatValue];
    154             CGFloat lineHeight = 7.5;//item上下间距
    155             
    156             _collectionHeightsArray[index][minHeightIndex] = [NSNumber numberWithFloat:minHeight+lineHeight+height];
    157             minHeightIndex = [self indexOfMinHeightWithSection:index];
    158             
    159             x = (spaceWidth + width) * minHeightIndex;
    160             
    161             y += [self minHeightWithSection:index];
    162             
    163         }
    164         
    165     }
    166     
    167 }
    168 
    169 
    170 /**
    171  返回collectionView的界面显示大小
    172  */
    173 - (CGSize)collectionViewContentSize{
    174     return  CGSizeMake(self.collectionView.frame.size.width, [self collectionHeight]);
    175 }
    176 
    177 
    178 /**
    179  将所有的layoutAttributes重写布局
    180  */
    181 - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    182     return _attributesArray;
    183 }
    184 @end
    .m文件
    @interface ForeverGuardFlowLayout()
    //存放每一列的高度
    @property (nonatomic, retain) NSMutableArray *columnHeightsArray;
    //每个section的每一列的高度
    @property (nonatomic, retain) NSMutableArray *collectionHeightsArray;
    //存放每一个cell的属性
    @property (nonatomic, retain) NSMutableArray *attributesArray;
    
    @end
    @implementation  ForeverGuardFlowLayout
    
    /**
     每个区的最小高度
     
     @param section 区索引
     @return 高度
     */
    - (CGFloat)minHeightWithSection:(NSInteger)section{
        CGFloat min = 1000000;
        for (NSNumber *height in _collectionHeightsArray[section]) {
            if (min > [height floatValue]) {
                min = [height floatValue];
            }
        }
        return min;
    }
    
    /**
     每个区的初始Y坐标
     
     @param section 区索引
     @return Y坐标
     */
    - (CGFloat)maxHeightWithSection:(NSInteger)section{
        
        if (section>0) {
            CGFloat max = 0;
            for (int i=0; i<section; i++) {
                max += [self maxHeightAboutSection:_collectionHeightsArray[i]];
            }
            return max;
        }else{
            return 0;
        }
        
    }
    
    
    /**
     每个区的最大高度
     
     @param dataArr 每个区的所有列的高度
     @return 最大高度
     */
    - (CGFloat)maxHeightAboutSection:(NSMutableArray *)dataArr{
        CGFloat max = 0;
        for (NSNumber *heigth  in dataArr) {
            if (max < [heigth floatValue]) {
                max = [heigth floatValue];
            }
        }
        return max;
        
    }
    
    /**
     collectionView的显示高度
     */
    - (CGFloat)collectionHeight{
        CGFloat max = 0;
        for (NSMutableArray *sectionArr in _collectionHeightsArray) {
            max += [self maxHeightAboutSection:sectionArr];
        }
        return max;
    }
    
    /**
     当前区的最小高度的索引
     
     @param section 当前区
     @return 最小高度的索引
     */
    - (NSUInteger)indexOfMinHeightWithSection:(NSInteger)section{
        NSUInteger index  = 0;
        NSMutableArray *sectionArr = _collectionHeightsArray[section];
        for (int i=0; i<sectionArr.count; i++) {
            CGFloat height = [sectionArr[i] floatValue];
            if (height == [self minHeightWithSection:section]) {
                index = i;
                return index;
            }
        }
        return index;
    }
    
    
    /**
     重写系统prepareLayout方法 (设置item的坐标等属性)
     */
    - (void)prepareLayout{
        [super prepareLayout];
        _attributesArray = [[NSMutableArray alloc] init];
        _columnHeightsArray = [NSMutableArray arrayWithCapacity:self.numberOfColumn];
        NSUInteger sectionCount = [self.collectionView numberOfSections];
        _collectionHeightsArray = [NSMutableArray arrayWithCapacity:sectionCount];
        for (int index = 0; index<sectionCount; index++) {
            NSMutableArray *columnArr = [NSMutableArray array];
            for (int i=0; i<self.numberOfColumn; i++) {
                [columnArr addObject:@0.0];
            }
            [_collectionHeightsArray addObject:columnArr];
        }
        CGFloat totalWidth = self.collectionView.frame.size.width;
        
        CGFloat x = 0;
        CGFloat y = 0;
        
        for (int index= 0; index<sectionCount; index++) {
            NSUInteger  itemCount = [self.collectionView numberOfItemsInSection:index];
            x = 0;
            y = [self maxHeightWithSection:index];
            for (int i=0; i<itemCount; i++) {
                NSUInteger numberIfSoace = self.numberOfColumn-1;
                CGFloat spaceWidth = 7.5;//item左右间距
                CGFloat width = (totalWidth - spaceWidth*numberIfSoace)/self.numberOfColumn;
                NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:index];
                CGSize imageSize =[self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath];
                CGFloat height = width * imageSize.height / imageSize.width;
                UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
                attributes.frame = CGRectMake(x, y, width, height);
                [_attributesArray addObject:attributes];
                
                NSUInteger minHeightIndex = [self indexOfMinHeightWithSection:index];
                CGFloat minHeight = [_collectionHeightsArray[index][minHeightIndex] floatValue];
                CGFloat lineHeight = 7.5;//item上下间距
                
                _collectionHeightsArray[index][minHeightIndex] = [NSNumber numberWithFloat:minHeight+lineHeight+height];
                minHeightIndex = [self indexOfMinHeightWithSection:index];
                
                x = (spaceWidth + width) * minHeightIndex;
                y = [self minHeightWithSection:index]+[self maxHeightWithSection:index];
            }
        }
    }
    
    /**
     返回collectionView的界面显示大小
     */
    - (CGSize)collectionViewContentSize{
        return  CGSizeMake(self.collectionView.frame.size.width, [self collectionHeight]);
    }
    
    /**
     将所有的layoutAttributes重写布局
     */
    - (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
        return _attributesArray;
    }
    @end
    ForeverGuard博客园
  • 相关阅读:
    [NPM] Avoid Duplicate Commands by Calling one NPM Script from Another
    [Algorithm] Dynamic programming: Find Sets Of Numbers That Add Up To 16
    [React] Refactor a Class Component with React hooks to a Function
    [Algorithm] Construct a Binary Tree and Binary Search
    设计模式(装饰者模式)
    IOS设计模式之二(门面模式,装饰器模式)
    IOS设计模式之三(适配器模式,观察者模式)
    linux内核源码阅读之facebook硬盘加速flashcache之五
    IOS设计模式之四(备忘录模式,命令模式)
    DRP总结
  • 原文地址:https://www.cnblogs.com/xianfeng-zhang/p/6401117.html
Copyright © 2020-2023  润新知