iOS中关于UICollectionView 最后一行元素垂直居中问题。

自定义UICollectionViewFlowLayout布局
代码直接奉上:

----h文件---

#import 
@interface VerticalCollectionAnyCenterLayout : UICollectionViewFlowLayout
    //传入一个item'的大小跟、行距离、自动计算布局等、
-(instancetype)initWithItemSize:(CGSize)size lineSpace:(CGFloat)margin_line;
@end

----m文件---

#import "VerticalCollectionAnyCenterLayout.h"
@interface VerticalCollectionAnyCenterLayout()
@property(nonatomic,strong)NSMutableArray * attrsArr;
@property (nonatomic,assign)NSInteger rows_line;//需要手动计算
@property (nonatomic,assign)CGFloat margin_inter;//需要手动计算item之间的距离
@property (nonatomic,assign)CGFloat margin_line;
@property (nonatomic,assign)CGSize size_item;

@end
@implementation VerticalCollectionAnyCenterLayout

-(instancetype)initWithItemSize:(CGSize)size lineSpace:(CGFloat)margin_line{
    if (self = [super init]){
        self.margin_line = margin_line;
        self.size_item = size;
    }
    return self;
}
-(void)caculation{
    [self.collectionView setNeedsLayout];
    CGSize size_collection =  self.collectionView.bounds.size;
    

    self.rows_line = (NSInteger)size_collection.width / self.size_item.width;
    self.margin_inter  = ((CGFloat)(size_collection.width - self.rows_line * self.size_item.width)) / ((CGFloat)(self.rows_line + 1));
    
    self.itemSize = self.size_item;
    self.minimumLineSpacing =  self.margin_line;
    self.minimumInteritemSpacing = self.margin_inter;
}
#pragma mark ---- 懒加载
-(NSMutableArray *)attrsArr
    {
        if(!_attrsArr){
            _attrsArr=[[NSMutableArray alloc] init];
        }
        return _attrsArr;
    }
    
-(void)prepareLayout
{
        [super prepareLayout];
        [self caculation];

        [self.attrsArr removeAllObjects];
        [self creatAttrs];
    
}
-(void)creatAttrs{
    //计算出每组有多少个
    NSInteger  count=[self.collectionView numberOfItemsInSection:0];
    /**
     * 因为不是继承流水布局 UICollectionViewFlowLayout
     * 所以我们需要自己创建 UICollectionViewLayoutAttributes
     */
    //如果是多组的话  需要2层循环
    for (int i=0; i *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        // 特别注意 在这个方法里 可以边滑动边刷新(添加) attrs 一劳永逸 如果只需要添加一次的话  可以把这些 prepareLayout方法中去
        return self.attrsArr;
    }
    
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
        return YES;
    
}
-(BOOL)shouldInvalidateLayoutForBoundsChange{
    return YES;
}
    
#pragma mark ---- 这个方法需要返回indexPath位置对应cell的布局属性
    /**
     *  //TODO:  这个方法主要用于 切换布局的时候 如果不适用该方法 就不会切换布局的时候会报错
     *   reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForItemAtIndexPath:  {length = 2, path = 0 - 2}'
     */
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
        // 主要是返回每个indexPath的attrs
        
        //创建UICollectionViewLayoutAttributes
        //这里需要 告诉 UICollectionViewLayoutAttributes 是哪里的attrs
        //计算出每组有多少个
        NSInteger section = indexPath.section;
        NSInteger count=[self.collectionView numberOfItemsInSection:section];

    
        UICollectionViewLayoutAttributes * attrs=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        NSInteger yushu =  count % self.rows_line;
    NSInteger zhengshu  = count / self.rows_line;
    NSInteger start = zhengshu * self.rows_line;
    if (indexPath.row >= start){
        //默认单行每个item都是等宽度
        CGFloat left_right_margin  = (self.collectionView.bounds.size.width  -
                                      self.size_item.width * yushu - (yushu - 1) * self.margin_inter) /2;
        NSInteger index_last_line =indexPath.row - start;
        CGRect frame  = attrs.frame;
        attrs.size = self.size_item;
        frame.size =  self.size_item;
        frame.origin.x = left_right_margin + (self.margin_inter + self.size_item.width)  * index_last_line;
        frame.origin.y =  (self.margin_line + self.size_item.height) * (indexPath.row / self.rows_line)+ self.margin_line;
        attrs.frame = frame;
        
    }
    else
    {
        CGRect frame  = attrs.frame;
        frame.size = self.size_item;
        attrs.size = self.size_item;
        frame.origin.x = (self.margin_inter + self.size_item.width) * (indexPath.row % self.rows_line) + self.margin_inter;
        frame.origin.y =  (self.margin_line + self.size_item.height) * (indexPath.row / self.rows_line) + self.margin_line;
        attrs.frame = frame;
        
    }
    if (indexPath.row == (count - 1)){///最后一个、计算contenSize
        CGSize contentSize = self.collectionView.contentSize;
        CGRect frame_last = attrs.frame;
        contentSize.height = CGRectGetMaxY(frame_last);
       self.collectionView.contentSize = contentSize;

    }
        return attrs;
}

@end

QQ20180810-0.png

使用方法直接给collectionView 一个layout即可、不用在代理中返回偏移量和itemSize

你可能感兴趣的:(iOS中关于UICollectionView 最后一行元素垂直居中问题。)