iOS自定义collectionViewLayout

2020-09-09  本文已影响0人  bugLife丶

iOS自定义collectionViewLayout

iOS开发collectionView也算用的比较广泛了,但是系统的collectionViewLayout有时候不能够满足开发需求,比如小红书那种瀑布流。这里讲一讲自定义collectionViewLayout,需要重写四个方法

  1. -(void)prepareLayout
    2.-(CGSize)collectionViewContentSize;
    3.-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
    4.-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

直接上代码

@interface SSCollectionViewLayout()

/** cell height arrays */
@property(nonatomic,strong)NSArray *cellHeightArrays;

/** attributes arrays */
@property(nonatomic,strong)NSMutableArray *attributesArrays;

/** cell array */
@property(nonatomic,strong)NSMutableArray *tempAttributesArrays;

@end

@implementation SSCollectionViewLayout

-(instancetype)initWithArrays:(NSArray *)cellHeightArrays
{
    if (self = [super init]) {
    
        self.cellHeightArrays = cellHeightArrays;
    }

    return self;
}

//自定义layout需要重写这些方法
-(void)prepareLayout
{
    [super prepareLayout];
    
    [self.attributesArrays  removeAllObjects];
    [self.tempAttributesArrays removeAllObjects];
    //获取当前collectionView对应区的item
    //获取senction全部个数
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    for (int i=0; i < count; i++) {
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow: i inSection:0]];
   
        [self.attributesArrays addObject:attributes];
    }
    
}

//返回collectionView的内容的尺寸
-(CGSize)collectionViewContentSize
{
    CGFloat maxContentHeight = CGRectGetMaxY([[self.tempAttributesArrays firstObject] frame]);
    for (UICollectionViewLayoutAttributes *attributes in self.tempAttributesArrays) {
        if (maxContentHeight  < attributes.frame.size.height) {
            maxContentHeight = CGRectGetMaxY(attributes.frame);
        }
    }
    return CGSizeMake(self.collectionView.bounds.size.width, maxContentHeight);
}

-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
    return self.attributesArrays;
}
///返回对应于indexPath的位置的cell的布局属性,返回指定indexPath的item的布局信息。子类必须重载该方法,该方法只能为cell提供布局信息,不能为补充视图和装饰视图提供。
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    CGFloat itemWidth = (self.collectionView.bounds.size.width  - (10 + 10 + 10 * 2))/3;
    CGFloat itemHeight = [self.cellHeightArrays[indexPath.row] floatValue];
    //在这里用上cellArrays了,横排最多显示3个
    if (self.tempAttributesArrays.count < 3) {//设置第一排rect
        [self.tempAttributesArrays addObject:attributes];
        NSLog(@"%ld",self.tempAttributesArrays.count);
        CGRect rect  = CGRectMake(10 +( itemWidth + 10) * (self.tempAttributesArrays.count - 1), 10, itemWidth, itemHeight);
        attributes.frame = rect;
    }else{
        
        UICollectionViewLayoutAttributes *fristAttributes = [self.tempAttributesArrays firstObject];
        CGFloat minY = CGRectGetMaxY(fristAttributes.frame);
        CGFloat Y = minY;
        NSInteger index = 0;
        CGRect itemFrame = CGRectMake(fristAttributes.frame.origin.x, CGRectGetMaxY(fristAttributes.frame) + 10, itemWidth, itemHeight);
        for (UICollectionViewLayoutAttributes *attri in self.tempAttributesArrays) {
            if (minY > CGRectGetMaxY(attri.frame)) {
                minY = CGRectGetMaxY(attri.frame);
                Y = minY;
                itemFrame = CGRectMake(attri.frame.origin.x, Y + 10, itemWidth, itemHeight);
                NSInteger currentIndex = [self.tempAttributesArrays indexOfObject:attri];
                index = currentIndex;
            }
        }
       
        attributes.frame = itemFrame;
        [self.tempAttributesArrays replaceObjectAtIndex:index withObject:attributes];

    }
   
    return attributes;
}

这里我们就实现了一个自定义layout,例子显示横屏3个item,高度通过动态传过来,实际开发中,需要跟后台商量,返回cell高度。

上一篇下一篇

猜你喜欢

热点阅读