iOS 瀑布流不規(guī)則布局,分區(qū)拓展完善(collectionView,網上很多 demo 只寫了一個分區(qū)的情況,這里做了一下擴展)

寫這篇文章的時候,其實網上已經有很多這樣的文章或 demo. 但是我在看的時候還是遇到了一點需要注意的地方.所以決定再寫一篇,說明一下我看網上的 demo 沒有注意到的地方.

1.寫之前先看一下大致的效果圖,如果不是你需要的 也就沒必要看下去,浪費你的時間了.

效果圖如下(可以設置參數,實現多列的效果)


2.該瀑布流多見于電商里面的商品展示布局.

3.說一下我在寫的時候遇到問題:? 紫色的是 imageView,我用 masonry 布局,設置 imageView 大小和 item 的大小一致,然后上下滑動的時候就出現了imageView 的 frame 和 item 的 frame 大小不一致的情況.

4.上面就是我遇到的問題,網上的 demo 大部分就是直接是 item,item 上面沒有放其他的控件,所以沒有這種問題.其實也主要是約束的問題. 下面把代碼貼出來和大家分享一下.

1.重寫 layout 布局

typedef CGFloat (^HeightBlock)(NSIndexPath *indexPath);

@interface MyCollectionViewLayout : UICollectionViewLayout

-(instancetype)initWithItemsHeightBlock:(HeightBlock)block;

@property (nonatomic,assign) NSInteger sectionCount;? //分區(qū)數

@property (nonatomic,assign) CGFloat colMargin;? //列間距

@property (nonatomic,assign) CGFloat colCount;? //列數

@property (nonatomic,assign) CGFloat rolMargin;? //行間距

@property (nonatomic,strong) NSMutableArray *colsHeight;? //每列總高度

@property (nonatomic,assign) CGFloat colWidth;? //列寬

@property (nonatomic,strong) HeightBlock heightBlock;

@end

@implementation MyCollectionViewLayout

-(instancetype)initWithItemsHeightBlock:(HeightBlock)block{

? self = [super init];??

if (self) {??

? ? self.heightBlock = block;? ??

? _sectionCount = 1; //默認分區(qū)數1? ? ?

? _colMargin = 5; //默認列間距5? ? ?

? _colCount = 4;? //默認列數 4 列?

? }? ?

return self;

}

-(NSMutableArray *)colsHeight{

? ? if (!_colsHeight) {?

? ? ? NSMutableArray *array = [NSMutableArray array];? ? ??

for (int i = 0; i < _colCount; i++) {? ? ? ? ? ? //這里可以設置初始高度? ? ? ? ??

[array addObject:@(0)];? ? ??

}? ? ?

? _colsHeight = [array mutableCopy];?

? }?

? return _colsHeight;

}

#pragma mark - 重寫下面系統(tǒng)的方法

//重新布局

-(void)prepareLayout{?

? [super prepareLayout];? ?

self.colWidth = (self.collectionView.frame.size.width - (self.colCount+1)*self.colMargin)/self.colCount;? ? self.colsHeight = nil;

}

//設置內容尺寸

-(CGSize)collectionViewContentSize{

? NSNumber *longest = self.colsHeight[0];??

for (int i = 0; i < self.colsHeight.count; i++) {

? ? ? NSNumber *rolHeight = self.colsHeight[i];?

? ? ? if (longest.floatValue < rolHeight.floatValue) {

? ? ? ? ? ? longest = rolHeight;? ? ??

}? ?

}? ?

return CGSizeMake(self.collectionView.frame.size.width, longest.floatValue);

}

//設置每個 item 的屬性

-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{

? UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];?

? NSNumber *shortest = self.colsHeight[0];??

NSInteger shortCol = 0;?

? for (int i = 0; i < self.colsHeight.count; i++) {? ?

? ? NSNumber *rolHeight = self.colsHeight[i];??

? ? if (shortest.floatValue > rolHeight.floatValue) {? ? ??

? ? shortest = rolHeight;? ? ? ? ? ? shortCol = i;? ? ??

}? ?

}??

CGFloat x = (shortCol+1)*self.colMargin + shortCol*self.colWidth;?

? CGFloat y = shortest.floatValue + self.colMargin;? ??

? CGFloat height = 0;??

if (self.heightBlock) {? ?

? ? height = self.heightBlock(indexPath);?

? }?

? attributes.frame = CGRectMake(x, y, self.colWidth, height);??

self.colsHeight[shortCol] = @(shortest.floatValue + self.colMargin + height);??

return attributes;

}

//獲取每個 item 的屬性

-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{

NSMutableArray *mutArr = [NSMutableArray array];

for (int j = 0; j < _sectionCount; j++) {

NSInteger items = [self.collectionView numberOfItemsInSection:j];

for (int i = 0; i < items; i++) {

UICollectionViewLayoutAttributes *att = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:j]];

[mutArr addObject:att];

}

}

return mutArr;

}

//這個方法是在 cell 重新布局時調用 repareLayout 方法

-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{

return YES;

}

@end

2.自定義 cell 里面需要注意的問題

@implementation Collection2ViewCell

-(instancetype)initWithFrame:(CGRect)frame{

self = [super initWithFrame:frame];

if (self) {

//獲取當前 cell 的寬和高

self.imageView = [UIImageView new];

self.imageView.backgroundColor = [UIColor purpleColor];

[self.contentView addSubview:self.imageView];

[self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {//注意這里給的是約束

make.edges.equalTo(self.contentView);

}];

//下面這種寫法就會造成上面我說的那種問題(具體原因是 item 的復用問題造成的,復用的時候不會再走該方法,但是 item 的高度賦值是會走的,所以造成 imageView 的 frame 和 cell 的 frame 不一致的情況)

//? ? ? ? [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {

//? ? ? ? ? ? make.centerX.mas_equalTo(self.mas_centerX);

//? ? ? ? ? ? make.centerY.mas_equalTo(self.mas_centerY);

//? ? ? ? ? ? make.width.mas_equalTo(frame.size.width);

//? ? ? ? ? ? make.height.mas_equalTo(frame.size.height);

//? ? ? ? }];

}

return self;

}

3.控制器里面的代碼

@interface Collection2ViewController ()

@property (nonatomic,strong) NSMutableArray *itemHeightArr;

@property (nonatomic,strong) MyCollectionViewLayout *flowLayout;

@property (nonatomic,strong) UICollectionView *collectionView;

@end

@implementation Collection2ViewControllerstatic

NSString * const reuseIdentifier = @"Cell";

- (void)viewDidLoad {?

? [super viewDidLoad];

? self.view.backgroundColor = [UIColor colorWithHexString:@"999999"];?

? self.title = @"UnNormalCollectionView";? ?

[self.view addSubview:self.collectionView];

}

-(UICollectionView *)collectionView{

? ? if (!_collectionView) {

? ? ? ? _collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, kWidth, kHeight-64) collectionViewLayout:self.flowLayout];? ??

? _collectionView.dataSource = self;? ??

? _collectionView.delegate = self;? ? ?

? _collectionView.backgroundColor = [UIColor whiteColor];? ? ?

? [_collectionView registerClass:[Collection2ViewCell class] forCellWithReuseIdentifier:reuseIdentifier];??

}? ?

return _collectionView;

}

-(UICollectionViewLayout *)flowLayout{

? if (!_flowLayout) {? ??

? _flowLayout = [[MyCollectionViewLayout alloc] initWithItemsHeightBlock:^CGFloat(NSIndexPath *indexPath) {? ??

? ? ? return [self.itemHeightArr[indexPath.item]floatValue];? ? ??

}];? ?

? ? _flowLayout.colCount = 2;? ? ?

? _flowLayout.sectionCount = 1;?

? }?

? return _flowLayout;

}

-(NSMutableArray *)itemHeightArr{??

if (!_itemHeightArr) {??

? ? NSMutableArray *arr = [NSMutableArray array];? ?

? ? for (int i = 0; i < 100; i++) {?

? ? ? ? ? [arr addObject:@(arc4random()%50+80)];? ??

? }?

? ? ? _itemHeightArr = [arr copy];

? }

? return _itemHeightArr;

}

#pragma mark-

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView

{

return 1;

}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section

{

return self.itemHeightArr.count;

}

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"點擊的是第 %ld 個item",indexPath.row);

}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

Collection2ViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

cell.contentView.backgroundColor = [UIColor redColor];

return cell;

}

@end

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市升敲,隨后出現的幾起案子京革,更是在濱河造成了極大的恐慌矢赁,老刑警劉巖吧史,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绊汹,死亡現場離奇詭異科吭,居然都是意外死亡纯出,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門是趴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涛舍,“玉大人,你說我怎么就攤上這事唆途「谎牛” “怎么了掸驱?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長没佑。 經常有香客問我毕贼,道長,這世上最難降的妖魔是什么蛤奢? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任鬼癣,我火速辦了婚禮,結果婚禮上啤贩,老公的妹妹穿的比我還像新娘待秃。我一直安慰自己,他們只是感情好痹屹,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布章郁。 她就那樣靜靜地躺著,像睡著了一般志衍。 火紅的嫁衣襯著肌膚如雪暖庄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天楼肪,我揣著相機與錄音培廓,去河邊找鬼。 笑死淹辞,一個胖子當著我的面吹牛医舆,可吹牛的內容都是我干的。 我是一名探鬼主播象缀,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼蔬将,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了央星?” 一聲冷哼從身側響起霞怀,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎莉给,沒想到半個月后毙石,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡颓遏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年徐矩,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叁幢。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡滤灯,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情鳞骤,我是刑警寧澤窒百,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站豫尽,受9級特大地震影響篙梢,放射性物質發(fā)生泄漏。R本人自食惡果不足惜美旧,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一渤滞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陈症,春花似錦蔼水、人聲如沸震糖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吊说。三九已至论咏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間颁井,已是汗流浹背厅贪。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留雅宾,地道東北人养涮。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像眉抬,于是被迫代替她去往敵國和親贯吓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容