瀑布流完成思緒
第一種就是用ScrollView來停止完成,由於它不具有復用的功用,因而我們需求自己寫一套相似復用的模塊來停止優化 第二種就是應用apple做好的復用模塊,自定義UIColletionLayout來完成瀑布流,想想也是第二種完成起來更快更優,OK,封裝一個小小的框架來試試默許兩列
其他案例
下面的動畫切換規劃也是自定義UICollectionLayout來停止規劃的,復雜的靜態圖片規劃展現其實就重寫幾個辦法就可以了
1.prepareLayout 每次重新刷新collectionView的時分會調用一次,做一些初始化的任務
2.layoutAttributesForElementsInRect 前往曾經制定好之後的每個cell對應的attribute屬性對象停止規劃
3.layoutAttributesForItemAtIndexPath 該辦法會不斷調用,每次cell出來就會依據對應的indexpath來停止辦法調用,因而關鍵規劃代碼就可以放置在這裡停止重新計算
4.collectionViewContentSize 計算全體的大小,完成滾動
下面拔出款式完成的傳送門
瀑布流完成剖析
1.根本變量的聲明
// 每一列的間距 static const CGFloat MKJDefaultColumnMargin = 10; // 每一行間距 static const CGFloat MKJDefaultRowMargin = 10; // 全體的上間距,左間距,下間距,右間距 static const UIEdgeInsets MKJDefaultEdgeInsets = {10,10,10,10}; // 默許是多少列 static const NSUInteger MKJDefaultColumnCounts = 2; @interface MKJWaterFallLayout () @property (nonatomic,strong) NSMutableArray *attributeArr; // cell屬性的數組 @property (nonatomic,strong) NSMutableArray *columnHeightarr; // 每列的高度數組 @end
2.初始化
// 每次刷新會調用一次 - (void)prepareLayout { [super prepareLayout]; // 每次重新刷新的時分肅清之前的一切高度值,默許就是UIEdg給定的top [self.columnHeightarr removeAllObjects]; for (NSInteger i = 0; i < [self columnCount]; i++) { [self.columnHeightarr addObject:@([self insetMargin].top)]; } // 每次刷新把對應的att屬性清空 [self.attributeArr removeAllObjects]; // 初始化一次每個cell對應的attribute屬性 NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (NSInteger i = 0; i < count; i++) { NSIndexPath *indexpath = [NSIndexPath indexPathForItem:i inSection:0]; UICollectionViewLayoutAttributes *attribute = [self layoutAttributesForItemAtIndexPath:indexpath]; [self.attributeArr addObject:attribute]; } }
3.關鍵計算代碼
// 前往attribute屬性數組決議最後的排布 - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { return self.attributeArr; } // 前往對應的indexpath下每個cell的屬性 cell的呈現會不斷刷新該辦法 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { // 初始化規劃屬性---> 對應的indexpath UICollectionViewLayoutAttributes *att = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; CGFloat collectionW = self.collectionView.frame.size.width; // 寬度是依據列數和間距固定算出來的 CGFloat width = (collectionW - [self insetMargin].left - [self insetMargin].right - ([self columnCount] - 1) * [self columnMargin]) / [self columnCount]; // 高度是依據代理的數據源前往比例計算的 CGFloat height = [self.delegate MKJWaterFallLayout:self heightForItemAtIndexPath:indexPath] * width; // X 和 Y值都是在找出最小column之後才干確定,中心就是依據列數,找出最小高度的那一列 // 先取出第一個默許是最小的 CGFloat minColumnHeight = [self.columnHeightArr[0] doubleValue]; // 默許最小的是第0列 NSUInteger finalCol = 0; for (NSInteger i = 1 ; i < [self columnCount]; i++) { CGFloat currentColHeight = [self.columnHeightArr[i] doubleValue]; if (minColumnHeight > currentColHeight) { minColumnHeight = currentColHeight; finalCol = i; } } // x,y值是依據最小高度列算出來的 CGFloat x = [self insetMargin].left + (width + [self columnMargin]) * finalCol; CGFloat y = minColumnHeight; // 當你是一個行排布的時分 默許是top值,不需求加間距 NSInteger count = indexPath.item; if ((count / ([self columnCount])) >= 1) { y += [self rowMargin]; } att.frame = CGRectMake(x, y, width, height); self.columnHeightArr[finalCol] = @(CGRectGetMaxY(att.frame)); return att; }
這裡的計算簡概括為就是對每個cell停止frame的計算
1.寬度的計算是依據列間距和全體左右間距以及行數停止限制,這些參數可以是固定值,也可以是代理傳出來的
2.高度的計算肯定是依據內部代理停止計算的
3.X值的計算是依據這個框架外部的每一列的高度數組停止之前的緩存高度,停止最小值計算,然後拿出最小值對應的列數,依據下面算出來的高度停止X值的計算
4.Y值的計算和X值一樣,依據給定的數組,比出最小高度列的列數,依據數組的高度,計算出對應的Y值,最終再停止數組對應列數的高度更新
4.獲取實踐能容大小,讓其可以滾動
// 計算出滾動區域的大小 - (CGSize)collectionViewContentSize { CGFloat maxColumHeight = [self.columnHeightArr[0] doubleValue]; for (NSInteger i = 1; i < [self columnCount]; i++) { CGFloat currentColHeight = [self.columnHeightArr[i] doubleValue]; if (maxColumHeight < currentColHeight) { maxColumHeight = currentColHeight; } } return CGSizeMake(0, maxColumHeight + [self insetMargin].bottom); }
5.這個小框架曾經封裝好了,復雜引見下用法
// 聲明如下 - (UICollectionView *)colletionView { if (_colletionView == nil) { MKJWaterFallLayout *layout = [[MKJWaterFallLayout alloc] init]; layout.delegate = self; UICollectionView *collectionV = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:layout]; collectionV.backgroundColor = [UIColor redColor]; [collectionV registerNib:[UINib nibWithNibName:productID bundle:nil] forCellWithReuseIdentifier:productID]; collectionV.delegate = self; collectionV.dataSource = self; _colletionView = collectionV; } return _colletionView; } // 外部行數,間距的控制 #pragma mark - waterfallLayoutDelegate - (CGFloat)MKJWaterFallLayout:(MKJWaterFallLayout *)layout heightForItemAtIndexPath:(NSIndexPath *)indexPath { // 前往寬度和高度比例 MKJProductModel *product = self.dataSource[indexPath.item]; return product.h / product.w; } // 控制列間距 - (CGFloat)columnMarginForWaterFallLayout:(MKJWaterFallLayout *)collectionViewLayout { return 10; } // 控制行間距 - (CGFloat)rowMarginForWaterFallLayout:(MKJWaterFallLayout *)collectionViewLayout { return 30; } // 控制列數 - (NSUInteger)columnCountForWaterFallLayout:(MKJWaterFallLayout *)collectionViewLayout { // if (self.dataSource.count > 50) { // return 3; // } return 3; } // 控制全體上左下右間距 - (UIEdgeInsets)insetForWaterFallLayout:(MKJWaterFallLayout *)collectionViewLayout { return UIEdgeInsetsMake(10, 10, 10, 10); }
Demo地址: http://xiazai.jb51.net/201702/yuanma/MKJWaterFallLayout_jb51.rar
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支持本站。
【android中UIColletionView瀑布流規劃完成思緒以及封裝的完成】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!