ios開發——解決UICollectionView的cell間距與設置不符問題

在用UICollectionView展示數據時,有時我們希望將cell的間距調成一個我們想要的值,然後查API可以看到有這麼一個屬性:

?
1
2
3
- (CGFloat)minimumInteritemSpacing {
    return0;
}

然而很多情況下我們會發現,這樣寫不能滿足我們的要求,cell之間仍然有一個不知道怎麼產生的間距。

我們知道cell的間距是由cell的大小itemSize和section的縮進sectionInset共同決定的,通過這兩個數據,UICollectionView動態地將cell放在相應的位置,然而即使我們接着調用inset方法也沒有用。

?
1
2
3
4
- (UIEdgeInsets)sectionInset
{
    returnUIEdgeInsetsMake(0,0,0,0);
}

<注:我想實現的是0間距,其他情況類似>

可以看到,繼承UICollectionViewFlowLayout後在- layoutAttributesForElementsInRect:方法中打印一下這些cell的frame的結果

?
1
2
3
4
5
6
7
8
9
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray* attributes = [[superlayoutAttributesForElementsInRect:rect] mutableCopy];
 
     
    for(UICollectionViewLayoutAttributes *attr in attributes) {
        NSLog(@"%@", NSStringFromCGRect([attr frame]));
    }
}

\

從上面兩行就可以看出來,我的高度是42.8,然而兩個cell的x值間距卻爲46,也就是說有大約3px的間距。


其實,正如minimumInteritemSpacing的名字一樣,這個屬性設置的是間距的最小值,那麼,我們實際需要的應該是一個"maximumInteritemSpacing",也就是最大間距。要解決這個問題,需要自己做一些計算。

依舊是繼承UICollectionViewFlowLayout,然後在- layoutAttributesForElementsInRect:方法中添加如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//從第二個循環到最後一個
    for(inti = 1; i < [attributes count]; ++i) {
        //當前attributes
        UICollectionViewLayoutAttributes *currentLayoutAttributes = attributes[i];
        //上一個attributes
        UICollectionViewLayoutAttributes *prevLayoutAttributes = attributes[i - 1];
        //我們想設置的最大間距,可根據需要改
        NSInteger maximumSpacing = 0;
        //前一個cell的最右邊
        NSInteger origin = CGRectGetMaxX(prevLayoutAttributes.frame);
        //如果當前一個cell的最右邊加上我們想要的間距加上當前cell的寬度依然在contentSize中,我們改變當前cell的原點位置
        //不加這個判斷的後果是,UICollectionView只顯示一行,原因是下面所有cell的x值都被加到第一行最後一個元素的後面了
        if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width) {
            CGRect frame = currentLayoutAttributes.frame;
            frame.origin.x = origin + maximumSpacing;
            currentLayoutAttributes.frame = frame;
        }
    }

原因註釋中已經解釋得非常詳細了。這樣就可以解決cell的間距問題了。再次運行,效果非常好:



修正版:

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
    
    UICollectionViewLayoutAttributes *firstLayoutAttributes = attributes[0];
    firstLayoutAttributes.frame = CGRectMake(self.sectionInset.left, firstLayoutAttributes.frame.origin.y, firstLayoutAttributes.frame.size.width, firstLayoutAttributes.frame.size.height);
    
    for(int i = 1; i < [attributes count]; ++i) {
        //當前attributes
        UICollectionViewLayoutAttributes *currentLayoutAttributes = attributes[i];
        //上一個attributes
        UICollectionViewLayoutAttributes *prevLayoutAttributes = attributes[i - 1];
        //我們想設置的最大間距,可根據需要改
        NSInteger maximumSpacing = _maxInteritemSpacing;
        //前一個cell的最右邊
        NSInteger origin = CGRectGetMaxX(prevLayoutAttributes.frame);
        //如果當前一個cell的最右邊加上我們想要的間距加上當前cell的寬度依然在contentSize中,我們改變當前cell的原點位置
        //不加這個判斷的後果是,UICollectionView只顯示一行,原因是下面所有cell的x值都被加到第一行最後一個元素的後面了
        if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width) {
            CGRect frame = currentLayoutAttributes.frame;
            frame.origin.x = origin + maximumSpacing;
            currentLayoutAttributes.frame = frame;
        }
    }
    
    return attributes;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章