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