iOS之簡單瀑布流的實現

來源:互聯網
上載者:User

標籤:

iOS之簡單瀑布流的實現 

 

前言

 

超簡單的瀑布流實現,這裡說一下筆者的思路,詳細代碼在這裡。

 

實現思路

 

collectionView能實現各中吊炸天的布局,其精髓就在於UICollectionViewLayout,因此我們要自訂一個layout來繼承系統的UICollectionViewLayout,所有工作都在這個類中進行。

 

1.定義所需屬性

 

瀑布流的思路就是,從上往下,那一列最短,就把下一個item放在哪一列,因此我們需要定義一個字典來記錄每一列的最大y值

 

每一個item都有一個attributes,因此定義一個數組來儲存每一個item的attributes。

 

我們還必須知道有多少列以及列間距、行間距、section到collectionView的邊距。

 

//總列數 @property (nonatomic, assign) NSInteger columnCount; //列間距 @property (nonatomic, assign) NSInteger columnSpacing; //行間距 @property (nonatomic, assign) NSInteger rowSpacing; //section到collectionView的邊距 @property (nonatomic, assign) UIEdgeInsets sectionInset; //儲存每一列最大y值的數組 @property (nonatomic, strong) NSMutableDictionary *maxYDic; //儲存每一個item的attributes的數組 @property (nonatomic, strong) NSMutableArray *attributesArray;

 

2.重寫系統方法

 

我們一共需要重寫4個方法

 

1)- (void)prepareLayout 2)- (CGSize)collectionViewContentSize 3)- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 4)- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect

 

- (void)prepareLayout 方法

 

布局前的一些準備工作都在這裡進行,初始化字典,有幾列就有幾個索引值對,key為第幾列,value為列的最大y值,初始值為上內邊距:

 

for  (int i = 0; i < self.columnCount; i++) {      self.maxYDic[@(i)] = @(self.sectionInset.top); }

 

建立每個item的attributes,並存入數組:

 

//根據collectionView擷取總共有多少個item NSInteger itemCount = [self.collectionView numberOfItemsInSection:0]; //為每一個item建立一個attributes並存入數組 for  (int i = 0; i < itemCount; i++) {      UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];      [self.attributesArray addObject:attributes]; }

 

- (CGSize)collectionViewContentSize 方法

 

用來計算collectionView的contentSize

 

一般瀑布流只能垂直滾動,不能水平滾動,因此contentSize.width = 0,我們只需要計算contentSize.height即可

 

從字典中找出最長列的最大y值,再加上下面的內邊距,即為contentSize.height

 

- (CGSize)collectionViewContentSize {      //假設第0列是最長的那列      __block NSNumber *maxIndex = @0;      //遍曆字典,找出最長的那一列      [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {          //如果maxColumn列的最大y值小於obj,則讓maxColumn等於obj所屬的列          if  ([self.maxYDic[maxIndex] floatValue] < obj.floatValue) {              maxIndex = key;          }      }];      //collectionView的contentSize.height就等於最長列的最大y值+下內邊距      return  CGSizeMake(0, [self.maxYDic[maxIndex] floatValue] + self.sectionInset.bottom); }

 

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 方法

 

該方法則用來設定每個item的attributes,在這裡,我們只需要簡單的設定每個item的attributes.frame即可

 

首先我們必須得知collectionView的尺寸,然後我們根據collectionView的寬度,以及列數、各個間距來計算每個item的寬度

 

item的寬度 = (collectionView的寬度 - 內邊距及列邊距) / 列數

 

CGFloat collectionViewWidth = self.collectionView.frame.size.width;//self.sectionInset.left:左邊距    self.sectionInset.right:右邊距//(self.columnCount - 1) * columnSpacing:一行中所有的列邊距CGFloat itemWidth = (collectionViewWidth - self.sectionInset.left - self.sectionInset.right - (self.columnCount - 1) * self.columnSpacing) / self.columnCount;

 

接下來計算item的座標,要想計算座標,那就必須知道最短的那一列,先遍曆字典,找出最短列是哪一列(minColumn)以及其最大y值。

 

item的y值就等於最短列的最大y值再加上行間距,x值就等於左邊距 + (item寬度 + 列間距) * minColumn

 

//找出最短的那一列 __block NSNumber *minIndex = @0; [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {      if  ([self.maxYDic[minIndex] floatValue] > obj.floatValue) {          minIndex = key;      } }]; //根據最短列的列數計算item的x值 CGFloat itemX = self.sectionInset.left + (self.columnSpacing + itemWidth) * minIndex.integerValue; //item的y值 = 最短列的最大y值 + 行間距 CGFloat itemY = [self.maxYDic[minIndex] floatValue] + self.rowSpacing;

 

接下來便是item的高度,我們應該根據圖片的原始大小以及計算出來的寬度,等比例縮放來計算高度,但是在layout類中,我們是拿不到圖片的,因此我們可以定義一個block屬性,或者代理,讓外界來計算並返回給我們,我們需要將item的寬度以及indexPath傳遞給外界:

 

@property (nonatomic, strong) CGFloat(^itemHeightBlock)(CGFloat itemHeight,NSIndexPath *indexPath);

 

根據傳回值來設定item的高度:

 

if (self.itemHeightBlock) itemHeight = self.itemHeightBlock(itemWidth, indexPath);

 

最後設定attributes的frame並更新字典:

 

//設定attributes的frame attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight); //更新字典中的最短列的最大y值 self.maxYDic[minIndex] = @(CGRectGetMaxY(attributes.frame));

 

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 方法

該方法用來返回rect範圍內,item的attributes

 

直接返回attributesArray即可

 

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return  self.attributesArray; }

 

使用

 

布局類寫完了,接下來就可以直接使用了

 

//建立布局對象 XRWaterfallLayout *waterfall = [[XRWaterfallLayout alloc] init]; //設定相關屬性 waterfall.columnCount = 3; //共多少列 waterfall.columnSpacing = 10; //列間距 waterfall.rowSpacing = 10; //行間距 waterfall.sectionInset = UIEdgeInsetsMake(10, 10 , 10, 10); //內邊距 [waterfall setItemHeightBlock:^CGFloat(CGFloat itemWidth, NSIndexPath *indexPath) { //根據圖片的原始大小,及顯示寬度,等比例縮放來計算顯示高度 XRImage *image = self.images[indexPath.item]; return  image.imageH / image.imageW * itemWidth; }]; collectionView.collectionViewLayout = waterfall; ...... ......

 

具體代碼請到這裡下載:https://github.com/codingZero/XRWaterfallLayout,覺得不錯的,請獻上你的star

 

iOS之簡單瀑布流的實現

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.