接上一篇文章,繼續處理collectionView在使用中出現的問題,若是你沒有遇到上面的問題這篇能夠跳過了,這裏就是處理collectionView中cell的間距不固定的問題。數組
要讓collectionView整齊排布,就要用到flowLayout,這裏能夠經過繼承UICollectionViewFlowLayout來從新對collectionView進行排布,這裏能夠詳細瞭解下UICollectionViewFlowLayout這個類,它是一個佈局類繼承自UICollectionViewLayout,下面重點說如下兩個ide
- (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,這裏就是返回全部佈局屬性的數組,佈局屬性有什麼用,固然就是用來佈局的,大小啊,中心點啊,透明度啊。。。具體的能夠移步這篇文字去一探究竟this
經過重寫這兩個方法,就能夠從新對content進行佈局了,這樣每一個cell的排列就能夠緊湊起來了
spa
直接上代碼
.net
- (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是好有影響的,好吧,有點深奧,就說這麼多吧。code
哦,最後還要在xib或者storyboard中的Identify中修改collectionView的class,這裏的MFChatRoomFilterCol就是繼承自UICollectionViewFlowLayout的自定義佈局,下面是運行的結果。看起來離目標又近了一步。orm