AutoLayout下CollectionView的自适应大小(二)

    接上一篇文章,继续处理collectionView在使用中出现的问题,如果你没有遇到上面的问题这篇可以跳过了,这里就是处理collectionView中cell的间距不固定的问题。

    要让collectionView整齐排布,就要用到flowLayout,这里可以通过继承UICollectionViewFlowLayout来重新对collectionView进行排布,这里可以详细了解下UICollectionViewFlowLayout这个类,它是一个布局类继承自UICollectionViewLayout,下面重点说以下两个

- (CGSize)collectionViewContentSize; // Subclasses must override this method and use it to return the width and height of the collection view’s content. These values represent the width and height of all the content, not just the content that is currently visible. The collection view uses this information to configure its own content size to facilitate scrolling.

- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect; // return an array layout attributes instances for all the views in the given rect

collectionViewContentSize 这个是必须重写的方法,用来返回collectionView的内容的大小,也就是说,并不是collectionView本身的大小,eg:collectionView的高度是10,而content的大小是100,那就会有滚动的效果。

layoutAttributesForElementsInRect,这里就是返回所有布局属性的数组,布局属性有什么用,当然就是用来布局的,大小啊,中心点啊,透明度啊。。。具体的可以移步这篇文字去一探究竟

通过重写这两个方法,就可以重新对content进行布局了,这样每个cell的排列就可以紧凑起来了

直接上代码

- (CGSize)collectionViewContentSize {
    
    CGSize size = CGSizeZero;
    NSInteger itemCount = 0;
    if ([self.collectionView.dataSource respondsToSelector:@selector(collectionView:numberOfItemsInSection:)]) {
        itemCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
    }
    if (CGSizeEqualToSize(size, CGSizeZero) && itemCount == 0) {
        return CGSizeZero;
    }

    NSInteger lineWidth = 50;
    NSUInteger rowCount = 1;
    for (int i = 1; i < itemCount; ++i) {
        NSArray* labels = [[MFAppModel sharedObject].chatroomModelEx getFullLabels];
        MFRoomLabel* currentRoomLabel = [labels objectAtIndex:i];
        NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:15]};
        CGSize currentLabelSize = [currentRoomLabel.name sizeWithAttributes:attribute];
        CGFloat cellWidth = MAX(50, currentLabelSize.width + 16);
        lineWidth = lineWidth + 15 + cellWidth;
        if (lineWidth > (NSInteger)self.collectionView.frame.size.width) {
            rowCount++;
            lineWidth = cellWidth;
        }
    }
    size.width = CGRectGetWidth(self.collectionView.frame);
    size.height = rowCount * self.itemSize.height + (rowCount - 1) * self.minimumLineSpacing  + self.sectionInset.top + self.sectionInset.bottom;
    
    return size;
}
- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
    NSMutableArray* attributes = [[super layoutAttributesForElementsInRect:rect] mutableCopy];

    for(int i = 1; i < [attributes count]; ++i) {
        
        NSArray* labels = [[MFAppModel sharedObject].chatroomModelEx getFullLabels];
        MFRoomLabel* roomLabel = [labels objectAtIndex:i];
        NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:15]};
        CGSize labelSize = [roomLabel.name sizeWithAttributes:attribute];
        UICollectionViewLayoutAttributes *currentLayoutAttributes = attributes[i];
        UICollectionViewLayoutAttributes *prevLayoutAttributes = attributes[i - 1];
        CGFloat cellWidth = MAX(50, labelSize.width + 16);
        currentLayoutAttributes.size = CGSizeMake(cellWidth, 24);
        NSInteger maximumSpacing = 15;
        NSInteger origin = CGRectGetMaxX(prevLayoutAttributes.frame);
        if (origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width) {
            CGRect frame = currentLayoutAttributes.frame;
            frame.origin.x = origin + maximumSpacing;
            currentLayoutAttributes.frame = frame;
            
        }
    }

    return attributes;
}

这里可能要讲解下layoutAttributesForElementsInRect,这里从第二个开始,每个cell的位置都是前一个cell的位置+maximumSpacing,如果不超过这一行的最大宽度,就改变当前cell的起始位置和大小(也即frame),如果超过了就不改变,那不改变是什么意思?就是保持原来的位置,这里的原来的位置可能和我们想象的不太一样,不是一开始定死的位置,而是经过调整后的位置,因为,这里改变前一个cell对后面的cell是好有影响的,好吧,有点深奥,就说这么多吧。

哦,最后还要在xib或者storyboard中的Identify中修改collectionView的class,这里的MFChatRoomFilterCol就是继承自UICollectionViewFlowLayout的自定义布局,下面是运行的结果。看起来离目标又近了一步。

AutoLayout下CollectionView的自适应大小(二)

AutoLayout下CollectionView的自适应大小(二)


你可能感兴趣的:(AutoLayout下CollectionView的自适应大小(二))