iOS 瀑布流布局实现详解
生活随笔
收集整理的這篇文章主要介紹了
iOS 瀑布流布局实现详解
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
新建文件繼承自UICollectionViewLayout .h內(nèi)容如下:
@class WaterFlowLayout; @protocol WaterFlowLayoutDelegate <NSObject>//使用delegate取得每一個(gè)Cell的高度 - (CGFloat)waterFlow:(WaterFlowLayout *)layout heightForCellAtIndexPath:(NSIndexPath *)indexPath;@end@interface WaterFlowLayout : UICollectionViewLayout//聲明協(xié)議 @property (nonatomic, weak) id <WaterFlowLayoutDelegate> delegate; //確定列數(shù) @property (nonatomic, assign) NSInteger colum; //確定內(nèi)邊距 @property (nonatomic, assign) UIEdgeInsets insetSpace; //確定每個(gè)cell之間的距離 @property (nonatomic, assign) NSInteger distance;@end 復(fù)制代碼.m實(shí)現(xiàn)內(nèi)容如下:
@interface WaterFlowLayout () //存儲列高的數(shù)組 @property (nonatomic, strong) NSMutableArray *columHeightArr; //存儲所有cell的尺寸信息 @property (nonatomic, strong) NSMutableArray *cellFrameArr;@end@implementation WaterFlowLayout//colum的set方法 - (void)setColum:(NSInteger)colum{if (_colum != colum) {_colum = colum;//將之前的布局信息失效,重新布局[self invalidateLayout];} }//distance的set方法 - (void)setDistance:(NSInteger)distance{if (_distance != distance) {_distance = distance;[self invalidateLayout];} }//insetSpace的set方法 - (void)setInsetSpace:(UIEdgeInsets)insetSpace{if (!UIEdgeInsetsEqualToEdgeInsets(_insetSpace, insetSpace)) {_insetSpace = insetSpace;[self invalidateLayout];} }//自定義layout需要重寫下面的幾個(gè)方法 //準(zhǔn)備布局,將item的位置信息計(jì)算出來 - (void)prepareLayout{//將位置信息和高度信息的數(shù)組實(shí)例化[self initDataArray];//初始化每一列的初始高度[self initColumHeightArray];//初始化計(jì)算出全部cell的高度,并且存入數(shù)組[self initAllCellHeight]; }//將位置信息和高度信息的數(shù)組實(shí)例化 - (void)initDataArray{//記錄當(dāng)前每一列的高度,所以我們只需要列數(shù)的空間就夠了。_columHeightArr = [NSMutableArray arrayWithCapacity:_colum];//記錄所有cell的尺寸信息_cellFrameArr = [NSMutableArray arrayWithCapacity:0]; }//初始化每一列的初始高度 - (void)initColumHeightArray{for (int i = 0; i < _colum; i++) {[_columHeightArr addObject:@(_insetSpace.top)];} }//初始化計(jì)算出全部cell的高度,并且存入數(shù)組 - (void)initAllCellHeight{//拿出第一組的全部cell的數(shù)量NSInteger allCellNumber = [self.collectionView numberOfItemsInSection:0];//取得整個(gè)collectionView的寬度CGFloat totalWidth = self.collectionView.frame.size.width;//取得一行中Cell的總寬度CGFloat itemAllWidth = totalWidth - _insetSpace.left - _insetSpace.right - _distance * (_colum - 1);//取得每一個(gè)cell的寬度CGFloat width = itemAllWidth/_colum;//循環(huán)計(jì)算每一個(gè)cell的高度并且將位置信息添加到數(shù)組中for (int i = 0; i < allCellNumber; i++) {//拿到當(dāng)前的列的信息NSInteger currentColum = [self getShortColum];//x偏移就是用當(dāng)前的列去乘以寬度和間距,并且加上內(nèi)邊距CGFloat xOffset = _insetSpace.left + currentColum * (width + _distance);//制造索引路徑NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];//取得y偏移CGFloat yOffset = [[_columHeightArr objectAtIndex:currentColum] floatValue] + _distance;//取得高度,由實(shí)現(xiàn)協(xié)議者提供CGFloat height = 0.f;if (_delegate && [_delegate respondsToSelector:@selector(waterFlow:heightForCellAtIndexPath:)]) {height = [_delegate waterFlow:self heightForCellAtIndexPath:indexPath];}//整理cell的尺寸信息CGRect frame = CGRectMake(xOffset, yOffset, width, height);//attributes是用來存儲當(dāng)前indexPath的cell的位置信息的UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];attributes.frame = frame;//將位置信息添加到cell尺寸數(shù)組中[_cellFrameArr addObject:attributes];//改變當(dāng)前列的高度_columHeightArr[currentColum] = @(frame.size.height + frame.origin.y);} }//取得當(dāng)前cell的尺寸 -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{return [_cellFrameArr objectAtIndex:indexPath.item]; }//根據(jù)rect去找出需要布局的cell的位置信息 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{//用來存儲可以展示的cell的位置信息NSMutableArray *temp = [NSMutableArray arrayWithCapacity:0];for (UICollectionViewLayoutAttributes *attributes in _cellFrameArr) {//如果取出的位置信息,在rect的范圍內(nèi),就將這個(gè)位置信息,裝入數(shù)組中。if (CGRectIntersectsRect(attributes.frame, rect)) {[temp addObject:attributes];}}return temp; }//指定collection的contentSize - (CGSize)collectionViewContentSize{//內(nèi)容寬度指定為collectionView的寬度(橫向不發(fā)生滾動)CGFloat width = self.collectionView.frame.size.width;//取出最長的列,將其高度定位長度CGFloat height = [self getLongColum];return CGSizeMake(width, height); }- (CGFloat)getLongColum{//記錄當(dāng)前最長的列號__block NSInteger currentColum = 0;//假設(shè)最長的列高度為0__block CGFloat longHeight = 0;//枚舉數(shù)組中的元素[_columHeightArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {if ([obj floatValue] > longHeight) {longHeight = [obj floatValue];currentColum = idx;}}];return longHeight + _insetSpace.bottom; }//取得最短的列 - (NSInteger)getShortColum{//記錄當(dāng)前最短的列號__block NSInteger currentColum = 0;//假設(shè)最短的列高度為float的最大值__block CGFloat shortHeight = MAXFLOAT;//枚舉數(shù)組中的元素[_columHeightArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {if ([obj floatValue] < shortHeight) {shortHeight = [obj floatValue];currentColum = idx;}}];return currentColum; }@end 復(fù)制代碼附:我的博客地址
總結(jié)
以上是生活随笔為你收集整理的iOS 瀑布流布局实现详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 学习笔记_12_文件共享服务
- 下一篇: 使用 FlipClock.js 制作精美