UICollectionView中Cell左對(duì)齊 居中 右對(duì)齊 等間距

最近在開發(fā)軟件的時(shí)候被產(chǎn)品經(jīng)理要求,要讓UICollectionView上面的cell之間的距離要被固定,但是cell得寬度不一定,所以一行有幾個(gè)cell其實(shí)不固定,所以其實(shí)cell之間的間距不一定,cell之間最終距離不是你設(shè)置的,而是由系統(tǒng)把一行中cell寬度減去,剩下的空白格平均分配的.所以我一開始寫出來的效果看起來不是很規(guī)則


屏幕快照

所以嘍,產(chǎn)品經(jīng)理不同意這樣,說看起來不是很規(guī)則锯茄,然后只能去網(wǎng)上找,做種找到了別人的一些例子窿给,最終弄出來一個(gè)貌似還能看的規(guī)則。


屏幕快照

最近需求還沒下來单起,所以把很久之前的這個(gè)代碼給重新折騰了一下抱怔,支持靠左睹酌,居中伞租,靠右楼眷,等間距對(duì)齊之景。整體邏輯也比之前清晰了一些斤富。

靠左等間距.png
居中等間距.png
靠右等間距.png
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger,AlignType){
    AlignWithLeft,
    AlignWithCenter,
    AlignWithRight
};
@interface JYEqualCellSpaceFlowLayout : UICollectionViewFlowLayout
//兩個(gè)Cell之間的距離
@property (nonatomic,assign)CGFloat betweenOfCell;
//cell對(duì)齊方式
@property (nonatomic,assign)AlignType cellType;

-(instancetype)initWthType : (AlignType)cellType;
//全能初始化方法 其他方式初始化最終都會(huì)?走到這里
-(instancetype)initWithType:(AlignType) cellType betweenOfCell:(CGFloat)betweenOfCell;

@end
#import "JYEqualCellSpaceFlowLayout.h"
@interface JYEqualCellSpaceFlowLayout(){
    //在居中對(duì)齊的時(shí)候需要知道這行所有cell的寬度總和
    CGFloat _sumCellWidth ;
}
@end

@implementation JYEqualCellSpaceFlowLayout
-(instancetype)init{
    return [self initWithType:AlignWithCenter betweenOfCell:5.0];
}
-(void)setBetweenOfCell:(CGFloat)betweenOfCell{
    _betweenOfCell = betweenOfCell;
    self.minimumInteritemSpacing = betweenOfCell;
}
-(instancetype)initWthType:(AlignType)cellType{
    return [self initWithType:cellType betweenOfCell:5.0];
}
-(instancetype)initWithType:(AlignType)cellType betweenOfCell:(CGFloat)betweenOfCell{
    self = [super init];
    if (self){
        self.scrollDirection = UICollectionViewScrollDirectionVertical;
        self.minimumLineSpacing = 5;
        self.minimumInteritemSpacing = 5;
        self.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5);
        _betweenOfCell = betweenOfCell;
        _cellType = cellType;
    }
    return self;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray * layoutAttributes_t = [super layoutAttributesForElementsInRect:rect];
    NSArray * layoutAttributes = [[NSArray alloc]initWithArray:layoutAttributes_t copyItems:YES];
    //用來臨時(shí)存放一行的Cell數(shù)組
    NSMutableArray * layoutAttributesTemp = [[NSMutableArray alloc]init];
    for (NSUInteger index = 0; index < layoutAttributes.count ; index++) {
        
        UICollectionViewLayoutAttributes *currentAttr = layoutAttributes[index]; // 當(dāng)前cell的位置信息
        UICollectionViewLayoutAttributes *previousAttr = index == 0 ? nil : layoutAttributes[index-1]; // 上一個(gè)cell 的位置信
        UICollectionViewLayoutAttributes *nextAttr = index + 1 == layoutAttributes.count ?
        nil : layoutAttributes[index+1];//下一個(gè)cell 位置信息
        
        //加入臨時(shí)數(shù)組
        [layoutAttributesTemp addObject:currentAttr];
        _sumCellWidth += currentAttr.frame.size.width;
        
        CGFloat previousY = previousAttr == nil ? 0 : CGRectGetMaxY(previousAttr.frame);
        CGFloat currentY = CGRectGetMaxY(currentAttr.frame);
        CGFloat nextY = nextAttr == nil ? 0 : CGRectGetMaxY(nextAttr.frame);
        //如果當(dāng)前cell是單獨(dú)一行
        if (currentY != previousY && currentY != nextY){
            if ([currentAttr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
                [layoutAttributesTemp removeAllObjects];
                _sumCellWidth = 0.0;
            }else if ([currentAttr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter]){
                [layoutAttributesTemp removeAllObjects];
                _sumCellWidth = 0.0;
            }else{
                [self setCellFrameWith:layoutAttributesTemp];
            }
        }
        //如果下一個(gè)cell在本行,這開始調(diào)整Frame位置
        else if( currentY != nextY) {
            [self setCellFrameWith:layoutAttributesTemp];
        }
    }
    return layoutAttributes;
}
//調(diào)整屬于同一行的cell的位置frame
-(void)setCellFrameWith:(NSMutableArray*)layoutAttributes{
    CGFloat nowWidth = 0.0;
    switch (_cellType) {
        case AlignWithLeft:
            nowWidth = self.sectionInset.left;
            for (UICollectionViewLayoutAttributes * attributes in layoutAttributes) {
                CGRect nowFrame = attributes.frame;
                nowFrame.origin.x = nowWidth;
                attributes.frame = nowFrame;
                nowWidth += nowFrame.size.width + self.betweenOfCell;
            }
            _sumCellWidth = 0.0;
            [layoutAttributes removeAllObjects];
            break;
            
        case AlignWithCenter:
            nowWidth = (self.collectionView.frame.size.width - _sumCellWidth - ((layoutAttributes.count - 1) * _betweenOfCell)) / 2;
            for (UICollectionViewLayoutAttributes * attributes in layoutAttributes) {
                CGRect nowFrame = attributes.frame;
                nowFrame.origin.x = nowWidth;
                attributes.frame = nowFrame;
                nowWidth += nowFrame.size.width + self.betweenOfCell;
            }
            _sumCellWidth = 0.0;
            [layoutAttributes removeAllObjects];
            break;
            
        case AlignWithRight:
            nowWidth = self.collectionView.frame.size.width - self.sectionInset.right;
            for (NSInteger index = layoutAttributes.count - 1 ; index >= 0 ; index-- ) {
                UICollectionViewLayoutAttributes * attributes = layoutAttributes[index];
                CGRect nowFrame = attributes.frame;
                nowFrame.origin.x = nowWidth - nowFrame.size.width;
                attributes.frame = nowFrame;
                nowWidth = nowWidth - nowFrame.size.width - _betweenOfCell;
            }
            _sumCellWidth = 0.0;
            [layoutAttributes removeAllObjects];
            break;
    }
}

@end

OC版本的Demo在這里
------------------------------------------------------分界線-----------------------------------------------------
下面是Swift版本的代碼

import UIKit
enum AlignType : NSInteger {
    case left = 0
    case center = 1
    case right = 2
}
class JYEqualCellSpaceFlowLayout: UICollectionViewFlowLayout {
    //兩個(gè)Cell之間的距離
    var betweenOfCell : CGFloat{
        didSet{
            self.minimumInteritemSpacing = betweenOfCell
        }
    }
    //cell對(duì)齊方式
    var cellType : AlignType = AlignType.center
    //在居中對(duì)齊的時(shí)候需要知道這行所有cell的寬度總和
    var sumCellWidth : CGFloat = 0.0
    
    override init() {
        betweenOfCell = 5.0
        super.init()
        scrollDirection = UICollectionViewScrollDirection.vertical
        minimumLineSpacing = 5
        sectionInset = UIEdgeInsetsMake(5, 5, 5, 5)
    }
    convenience init(_ cellType:AlignType){
        self.init()
        self.cellType = cellType
    }
    convenience init(_ cellType: AlignType, _ betweenOfCell: CGFloat){
        self.init()
        self.cellType = cellType
        self.betweenOfCell = betweenOfCell
    }
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        
        let layoutAttributes_super : [UICollectionViewLayoutAttributes] = super.layoutAttributesForElements(in: rect) ?? [UICollectionViewLayoutAttributes]()
        let layoutAttributes:[UICollectionViewLayoutAttributes] = NSArray(array: layoutAttributes_super, copyItems:true)as! [UICollectionViewLayoutAttributes]
        var layoutAttributes_t : [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
        for index in 0..<layoutAttributes.count{
            
            let currentAttr = layoutAttributes[index]
            let previousAttr = index == 0 ? nil : layoutAttributes[index-1]
            let nextAttr = index + 1 == layoutAttributes.count ?
                nil : layoutAttributes[index+1]
            
            layoutAttributes_t.append(currentAttr)
            sumCellWidth += currentAttr.frame.size.width
            
            let previousY :CGFloat = previousAttr == nil ? 0 : previousAttr!.frame.maxY
            let currentY :CGFloat = currentAttr.frame.maxY
            let nextY:CGFloat = nextAttr == nil ? 0 : nextAttr!.frame.maxY
            
            if currentY != previousY && currentY != nextY{
                if currentAttr.representedElementKind == UICollectionElementKindSectionHeader{
                    layoutAttributes_t.removeAll()
                    sumCellWidth = 0.0
                }else if currentAttr.representedElementKind == UICollectionElementKindSectionFooter{
                    layoutAttributes_t.removeAll()
                    sumCellWidth = 0.0
                }else{
                    self.setCellFrame(with: layoutAttributes_t)
                    layoutAttributes_t.removeAll()
                    sumCellWidth = 0.0
                }
            }else if currentY != nextY{
                self.setCellFrame(with: layoutAttributes_t)
                layoutAttributes_t.removeAll()
                sumCellWidth = 0.0
            }
        }
        return layoutAttributes
    }
    
    /// 調(diào)整Cell的Frame
    ///
    /// - Parameter layoutAttributes: layoutAttribute 數(shù)組
    func setCellFrame(with layoutAttributes : [UICollectionViewLayoutAttributes]){
        var nowWidth : CGFloat = 0.0
        switch cellType {
        case AlignType.left:
            nowWidth = self.sectionInset.left
            for attributes in layoutAttributes{
                var nowFrame = attributes.frame
                nowFrame.origin.x = nowWidth
                attributes.frame = nowFrame
                nowWidth += nowFrame.size.width + self.betweenOfCell
            }
            break;
        case AlignType.center:
            nowWidth = (self.collectionView!.frame.size.width - sumCellWidth - (CGFloat(layoutAttributes.count - 1) * betweenOfCell)) / 2
            for attributes in layoutAttributes{
                var nowFrame = attributes.frame
                nowFrame.origin.x = nowWidth
                attributes.frame = nowFrame
                nowWidth += nowFrame.size.width + self.betweenOfCell
            }
            break;
        case AlignType.right:
            nowWidth = self.collectionView!.frame.size.width - self.sectionInset.right
            for var index in 0 ..< layoutAttributes.count{
                index = layoutAttributes.count - 1 - index
                let attributes = layoutAttributes[index]
                var nowFrame = attributes.frame
                nowFrame.origin.x = nowWidth - nowFrame.size.width
                attributes.frame = nowFrame
                nowWidth = nowWidth - nowFrame.size.width - betweenOfCell
            }
            break;
        }
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Swift版本Demo在這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锻狗,一起剝皮案震驚了整個(gè)濱河市满力,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屋谭,老刑警劉巖脚囊,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異桐磁,居然都是意外死亡悔耘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門我擂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衬以,“玉大人,你說我怎么就攤上這事校摩】淳” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵衙吩,是天一觀的道長(zhǎng)互妓。 經(jīng)常有香客問我,道長(zhǎng)坤塞,這世上最難降的妖魔是什么冯勉? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮摹芙,結(jié)果婚禮上灼狰,老公的妹妹穿的比我還像新娘。我一直安慰自己浮禾,他們只是感情好交胚,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布份汗。 她就那樣靜靜地躺著,像睡著了一般蝴簇。 火紅的嫁衣襯著肌膚如雪杯活。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天军熏,我揣著相機(jī)與錄音轩猩,去河邊找鬼卷扮。 笑死荡澎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的晤锹。 我是一名探鬼主播摩幔,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼鞭铆!你這毒婦竟也來了或衡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤车遂,失蹤者是張志新(化名)和其女友劉穎封断,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舶担,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坡疼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衣陶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柄瑰。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖剪况,靈堂內(nèi)的尸體忽然破棺而出教沾,到底是詐尸還是另有隱情,我是刑警寧澤译断,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布授翻,位于F島的核電站,受9級(jí)特大地震影響孙咪,放射性物質(zhì)發(fā)生泄漏堪唐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一该贾、第九天 我趴在偏房一處隱蔽的房頂上張望羔杨。 院中可真熱鬧,春花似錦杨蛋、人聲如沸兜材。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曙寡。三九已至糠爬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間举庶,已是汗流浹背执隧。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留户侥,地道東北人镀琉。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蕊唐,于是被迫代替她去往敵國和親屋摔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫替梨、插件钓试、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,033評(píng)論 4 62
  • 嗯哼嗯哼蹦擦擦~~~ 轉(zhuǎn)載自:https://github.com/Tim9Liu9/TimLiu-iOS 目錄 ...
    philiha閱讀 4,848評(píng)論 0 6
  • 自律弓熏,是人生最尊貴的標(biāo)配 黃抒揚(yáng) 1 年前 作者:國館 來源:國館 鏈接:國館丨自律,是人生最尊貴的標(biāo)配 著作權(quán)歸...
    天下熙熙皆為利來啊閱讀 164評(píng)論 0 1
  • 怎樣的孤獨(dú)是你認(rèn)為的孤獨(dú) 是走在熙熙攘攘的街頭沒有談笑風(fēng)生的朋友糠睡,還是深夜在安靜垂淚沒有聽你聲音的耳朵挽鞠,又或者是不...
    賴青閱讀 212評(píng)論 0 1