UICollectionView的简单使用(二)— 瀑布流(石工布局)
有了上一篇的基础,发现现在常用UICollectionView的布局是瀑布流(石工布局),首先我看看默认大小不一的布局。
1.默认布局
我们在ViewController.m文件添加一下代码
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { CGFloat randomHeight = 100 + (arc4random() % 140); return CGSizeMake(100, randomHeight);//100-240之间 }
模拟器运行如下:
这就是默认的情况,但不是我们想要的情况。
2.瀑布流(石工布局)
接下来就要创建一个UICollectionViewLayout的子类,布局子类覆盖父类的方法
2.1 在YFCollectionViewLayout.h文件中添加
#import <UIKit/UIKit.h> @class YFCollectionViewLayout; @protocol YFCollectionViewLayoutDelegate <NSObject> @required - (CGFloat)collectionView:(UICollectionView *) collectionView layout:(YFCollectionViewLayout *)layout heightForItemAtIndexPath:(NSIndexPath *) indexPath; @end @interface YFCollectionViewLayout : UICollectionViewLayout /** * 列数 */ @property (nonatomic, assign) NSUInteger numberOfColumns; /** * 间距 */ @property (nonatomic, assign) CGFloat interItemSpacing; @property (nonatomic, weak) id<YFCollectionViewLayoutDelegate> delegate; @end
2.2 在YFCollectionViewLayout.m文件中
子类需要覆盖的方法有
/** * 布局准备方法,可以把一些计算的东西放到这里 */ - (void)prepareLayout; /** * 每个子控件的一些属性 */ - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect; /** * 集合视图整体大小 * */ - (CGSize)collectionViewContentSize;
// // YFCollectionViewLayout.m // WaterfallFlowCollection // // Created by apple on 15/12/15. // Copyright © 2015年 蓝天的梦想. All rights reserved. // #import "YFCollectionViewLayout.h" @interface YFCollectionViewLayout () /** * 最后列的Y值 */ @property (nonatomic, strong) NSMutableDictionary *lastYValueForColumn; /** * 布局信息 */ @property (nonatomic, strong) NSMutableDictionary *layoutInfo; @end @implementation YFCollectionViewLayout /** * 布局准备方法,可以把一些计算的东西放到这里 */ -(void) prepareLayout { [super prepareLayout]; self.lastYValueForColumn = [NSMutableDictionary dictionary]; CGFloat currentColumn = 0; CGFloat fullWidth = self.collectionView.frame.size.width; CGFloat availableSpaceExcludingPadding = fullWidth - (self.interItemSpacing * (self.numberOfColumns + 1)); CGFloat itemWidth = availableSpaceExcludingPadding / self.numberOfColumns; self.layoutInfo = [NSMutableDictionary dictionary]; NSIndexPath *indexPath; NSInteger numSections = [self.collectionView numberOfSections]; for(NSInteger section = 0; section < numSections; section++) { NSInteger numItems = [self.collectionView numberOfItemsInSection:section]; for(NSInteger item = 0; item < numItems; item++){ indexPath = [NSIndexPath indexPathForItem:item inSection:section]; UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; CGFloat x = self.interItemSpacing + (self.interItemSpacing + itemWidth) * currentColumn; CGFloat y = [self.lastYValueForColumn[@(currentColumn)] doubleValue]; CGFloat height = [((id<YFCollectionViewLayoutDelegate>)self.collectionView.delegate) collectionView:self.collectionView layout:self heightForItemAtIndexPath:indexPath]; itemAttributes.frame = CGRectMake(x, y, itemWidth, height); y+= height; y += self.interItemSpacing; self.lastYValueForColumn[@(currentColumn)] = @(y); currentColumn ++; if(currentColumn == self.numberOfColumns) currentColumn = 0; self.layoutInfo[indexPath] = itemAttributes; } } } /** * 每个子控件的一些属性 */ - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{ NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.layoutInfo.count]; [self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath, UICollectionViewLayoutAttributes *attributes, BOOL *stop) { if (CGRectIntersectsRect(rect, attributes.frame)) { [allAttributes addObject:attributes]; } }]; return allAttributes; } /** * 集合视图整体大小 * */ -(CGSize) collectionViewContentSize { NSUInteger currentColumn = 0; CGFloat maxHeight = 0; do { CGFloat height = [self.lastYValueForColumn[@(currentColumn)] doubleValue]; if(height > maxHeight) maxHeight = height; currentColumn ++; } while (currentColumn < self.numberOfColumns); return CGSizeMake(self.collectionView.frame.size.width, maxHeight); } @end
打开Storyboard的文件,给CollectionViewLayout设置类名
打开ViewCollection.m文件,拖线并设置代理
设置间距和列数
设置代理方法
模拟器运行结果如下
下载地址:https://github.com/yifazhang/WaterfallFlowCollection