自定義UICollectionViewLayout之瀑布流的封裝實(shí)現(xiàn)

當(dāng)系統(tǒng)給出的布局屬性UIcollectionViewFlowLayout不能滿(mǎn)足我們的需求的時(shí)候,我們就需要自己來(lái)定義一個(gè)我們需要的布局屬性,來(lái)完成我們的需求,那么該怎么做呢?下面我將給出一個(gè)詳細(xì)的demo給大家用參考,代碼中均有詳細(xì)的注釋解釋,希望對(duì)大家能有幫助.

//  XY_WaterFlowLayout.h
//  UI15_CustomCollectionViewLayout
//
//  Created by 歲變 on 16/8/3.
//  Copyright ? 2016年 歲變. All rights reserved.
//

#import <UIKit/UIKit.h>

@protocol XY_WaterFlowLayoutDelegate <NSObject>

- (CGFloat)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
                   width:(CGFloat)width
heightForItemAtIndexPath:(NSIndexPath *)indexPath;
@end

//自定義布局繼承于 UICollectionViewLayout

@interface XY_WaterFlowLayout : UICollectionViewLayout
@property (nonatomic, weak) id <XY_WaterFlowLayoutDelegate> delegate;

@property (nonatomic, assign) CGFloat itemWidth; //item的寬度
@property (nonatomic, assign) CGFloat horizontalSpace;//行間距
@property (nonatomic, assign) CGFloat verticalSpace;//豎向間距
@property (nonatomic, assign) UIEdgeInsets sectionInsets;//邊距
@property (nonatomic, assign) NSInteger numberOfColumns; //列數(shù)

@end

//
//  XY_WaterFlowLayout.m
//  UI15_CustomCollectionViewLayout
//
//  Created by 歲變 on 16/8/3.
//  Copyright ? 2016年 歲變. All rights reserved.
//

#import "XY_WaterFlowLayout.h"

@interface XY_WaterFlowLayout ()


@property (nonatomic, strong) NSMutableArray< UICollectionViewLayoutAttributes *> *attributesArrary; //保存布局屬性的數(shù)組
@property (nonatomic, strong) NSMutableArray *arrHeightForColumns;//保存每列的高度

@property (nonatomic, assign) NSInteger shortestColumnsIndex; //最短列坐標(biāo)
@property (nonatomic, assign) NSInteger longestColumnsIndex; //最長(zhǎng)列坐標(biāo)

@end

@implementation XY_WaterFlowLayout

- (instancetype)init {
    
    self = [super init];
    if (self) {
        //默認(rèn)值 :列數(shù)2
        //      :橫向間距10
        //      :縱向間距10
        //      :據(jù)四周邊距 10 10 10 10
        _numberOfColumns = 2;
        _horizontalSpace = 10;
        _verticalSpace = 10;
        _sectionInsets = UIEdgeInsetsMake(10, 10, 10, 10);
    }
    return self;
}

- (CGFloat)itemWidth {
    
    self.itemWidth = (self.collectionView.frame.size.width - (_numberOfColumns - 1) * _horizontalSpace - _sectionInsets.left - _sectionInsets.right) / _numberOfColumns;
    return _itemWidth;
}


//自定義layout 必須重寫(xiě)三個(gè)方法

- (void)prepareLayout {
    [super prepareLayout];
    
    self.attributesArrary = [NSMutableArray array];
    self.arrHeightForColumns = [NSMutableArray array];
    //給每一列添加上邊距的距離
    [self addTopSectionInsetsForColums];
    
    //獲取item 的個(gè)數(shù) [self.collectionView numberOfItemsInSection:0]
    for (int i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) {
        //為每個(gè)item創(chuàng)建布局屬性 并添加到數(shù)組中
        UICollectionViewLayoutAttributes *layoutAttributes = [self setLayoutAttributesForItems:[NSIndexPath indexPathForItem:i inSection:0]];
        [_attributesArrary addObject:layoutAttributes];
    }
}

//返回每個(gè)item的布局屬性
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    return _attributesArrary;
}

//負(fù)責(zé)滾動(dòng)范圍
- (CGSize)collectionViewContentSize {
    //獲取最長(zhǎng)列坐標(biāo)
    NSInteger longextIndex = [self getLongestColumnsIndex];
    //獲取最長(zhǎng)列的長(zhǎng)度
    CGFloat longestHeight = [_arrHeightForColumns[longextIndex] floatValue];
    //獲取collectionView的size
    CGSize contentSize = self.collectionView.frame.size;
    contentSize.height = longestHeight + _sectionInsets.bottom;
    return contentSize;
}


//給每一刻加上上邊距
- (void)addTopSectionInsetsForColums {
    
    for (int i = 0; i < _numberOfColumns; i++) {
        [_arrHeightForColumns addObject:@(_sectionInsets.top)];
    }
}




//生成每個(gè)item的不屬性 主要是fram屬性
- (UICollectionViewLayoutAttributes *)setLayoutAttributesForItems:(NSIndexPath *)indexPath {
    
    UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    //item的原點(diǎn)坐標(biāo)
    CGPoint origin = [self originForItem];
    
    //通過(guò)代理獲取寬和高
    CGFloat height = 0;
    if ([self.delegate respondsToSelector:@selector(collectionView:layout:width:heightForItemAtIndexPath:)]) {
        height = [self.delegate collectionView:self.collectionView layout:self width:self.itemWidth heightForItemAtIndexPath:indexPath];
    }
    
    layoutAttributes.frame = CGRectMake(origin.x, origin.y, self.itemWidth, height);
    
    //更新數(shù)組里的列高度
    _arrHeightForColumns[_shortestColumnsIndex]  = @(origin.y + height);
    
    return layoutAttributes;

}

//計(jì)算原點(diǎn)坐標(biāo)
- (CGPoint)originForItem {
    
    //最短列
    _shortestColumnsIndex = [self getShortestColumnsIndex];
    //計(jì)算原點(diǎn)坐標(biāo).x  左邊距 + (item寬度 + item橫向間距) * shorestColumnsIndex
    CGFloat x = _sectionInsets.left + (self.itemWidth + self.horizontalSpace) * _shortestColumnsIndex;
    
    //計(jì)算原點(diǎn)坐標(biāo).y
    CGFloat y = [_arrHeightForColumns[_shortestColumnsIndex] floatValue] + _verticalSpace;
    
    CGPoint origin = CGPointMake(x, y);
    return origin;
}


//記錄最短列的坐標(biāo)
- (NSInteger) getShortestColumnsIndex {
    //記錄最短列
    NSInteger shortestIndex = 0;
    //記錄最短高度
    CGFloat shortestHeight = MAXFLOAT;
    
    for (int i = 0; i < self.arrHeightForColumns.count; i++) {
        
        CGFloat currentHeight = [self.arrHeightForColumns[i] floatValue];
        if (currentHeight < shortestHeight) {
            shortestHeight = currentHeight;
            shortestIndex = i;
        }
    }
    return shortestIndex;
}

//記錄最長(zhǎng)列的坐標(biāo)
- (NSInteger)getLongestColumnsIndex {
    //記錄最長(zhǎng)列
    NSInteger longestIndex = 0;
    //最長(zhǎng)列高度
    CGFloat longestHight = 0;
    
    for (int i = 0; i < _arrHeightForColumns.count; i++) {
        CGFloat currentHeight = [self.arrHeightForColumns[i] floatValue];
        if (currentHeight > longestHight) {
            longestHight = currentHeight;
            longestIndex = i;
        }
    }
    return longestIndex;
}



@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杈绸,一起剝皮案震驚了整個(gè)濱河市杠人,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌龙屉,老刑警劉巖满俗,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件作岖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡五芝,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)枢步,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人价捧,你說(shuō)我怎么就攤上這事丑念。” “怎么了结蟋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵脯倚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我嵌屎,道長(zhǎng)推正,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任宝惰,我火速辦了婚禮植榕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尼夺。我一直安慰自己尊残,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般握截。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上慰毅,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音扎阶,去河邊找鬼汹胃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛东臀,可吹牛的內(nèi)容都是我干的着饥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼惰赋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼贱勃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤贵扰,失蹤者是張志新(化名)和其女友劉穎仇穗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體戚绕,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纹坐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舞丛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耘子。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖球切,靈堂內(nèi)的尸體忽然破棺而出谷誓,到底是詐尸還是另有隱情,我是刑警寧澤吨凑,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布捍歪,位于F島的核電站,受9級(jí)特大地震影響鸵钝,放射性物質(zhì)發(fā)生泄漏糙臼。R本人自食惡果不足惜恩商,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望揽乱。 院中可真熱鬧粟矿,春花似錦、人聲如沸嚷炉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)哗讥。三九已至胞枕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背队询。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工构诚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人范嘱。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像叠聋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子碌补,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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