UICollectionView瀑布流效果就是這么cool~

瀑布.jpg

實現(xiàn)思路:

  • 自定義UICollectionViewLayout布局
  • 根據(jù)item的相關屬性, margin等設置每一個item的布局屬性
  • 每次設置item的布局屬性時找到當前collectionView的所有列中高度最小的列, 把下一個item放在高度最小的列下面進行排布

1.自定義UICollectionViewLayout布局

  • 1>重寫prepareLayout方法進行每次刷新的初始化設置
- (void)prepareLayout {
[super prepareLayout];
  
  self.contentHeight = 0;
  
  // 清除以前計算的所有高度
  [self.columnHeights removeAllObjects];
  for (NSInteger i = 0; i < self.columnCount; i++) {
      [self.columnHeights addObject:@(self.edgeInsets.top)];
  }
  
  // 清除之前所有的布局屬性
  [self.attrsArray removeAllObjects];
  // 開始創(chuàng)建每一個cell對應的布局屬性
  NSInteger count = [self.collectionView numberOfItemsInSection:0];
  for (NSInteger i = 0; i < count; i++) {
      // 創(chuàng)建位置
      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
      // 獲取indexPath位置cell對應的布局屬性
      UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
      [self.attrsArray addObject:attrs];
  }
}
  • 2>重寫layoutAttributesForElementsInRect方法, 返回所有的布局屬性
/**
* 決定cell的排布
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
  return self.attrsArray;
}
  • 3>重點重寫layoutAttributesForItemAtIndexPath方法, 實現(xiàn)對每個item的布局屬性進行計算, 返回每個UICollectionViewCell的布局屬性
/**
* 返回indexPath位置cell對應的布局屬性
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
  // 創(chuàng)建布局屬性
  UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
  
  // collectionView的寬度
  CGFloat collectionViewW = self.collectionView.frame.size.width;
  
  // 設置布局屬性的frame
  CGFloat w = (collectionViewW - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
  CGFloat h = [self.delegate waterflowLayout:self heightForItemAtIndex:indexPath.item itemWidth:w];
  
  // 找出高度最短的那一列
  NSInteger destColumn = 0;
  CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];
  for (NSInteger i = 1; i < self.columnCount; i++) {
      // 取得第i列的高度
      CGFloat columnHeight = [self.columnHeights[i] doubleValue];
      
      if (minColumnHeight > columnHeight) {
          minColumnHeight = columnHeight;
          destColumn = i;
      }
  }
  
  CGFloat x = self.edgeInsets.left + destColumn * (w + self.columnMargin);
  CGFloat y = minColumnHeight;
  if (y != self.edgeInsets.top) {
      y += self.rowMargin;
  }
  attrs.frame = CGRectMake(x, y, w, h);
  
  // 更新最短那列的高度
  self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));
  
  // 記錄內(nèi)容的高度
  CGFloat columnHeight = [self.columnHeights[destColumn] doubleValue];
  if (self.contentHeight < columnHeight) {
      self.contentHeight = columnHeight;
  }
  return attrs;
}
  • 4>重寫collectionViewContentSize返回瀑布流的內(nèi)容尺寸
- (CGSize)collectionViewContentSize {
return CGSizeMake(0, self.contentHeight + self.edgeInsets.bottom);
}

2.仿照UITableView瀑布流進行封裝

  • 定義代理MRWaterflowLayoutDelegate和方法
      @protocol MRWaterflowLayoutDelegate <NSObject>
      @required
      // 對應item的高度(必須實現(xiàn))
      - (CGFloat)waterflowLayout:(MRWaterflowLayout *)waterflowLayout heightForItemAtIndex:(NSUInteger)index itemWidth:(CGFloat)itemWidth;

      @optional
      // 瀑布流的列數(shù)
      - (CGFloat)columnCountInWaterflowLayout:(MRWaterflowLayout *)waterflowLayout;
      // 瀑布流每列之間的間距
      - (CGFloat)columnMarginInWaterflowLayout:(MRWaterflowLayout *)waterflowLayout;
      // 瀑布流每行元素之間的間距
      - (CGFloat)rowMarginInWaterflowLayout:(MRWaterflowLayout *)waterflowLayout;
      // 整個瀑布流的邊距
      - (UIEdgeInsets)edgeInsetsInWaterflowLayout:(MRWaterflowLayout *)waterflowLayout;
    @end
  • 將代理MRWaterflowLayoutDelegate設置為自定義布局的屬性
/** 瀑布流代理 */
@property (nonatomic, weak) id<MRWaterflowLayoutDelegate> delegate;
  • 如果實現(xiàn)了代理則使用代理返回的數(shù)據(jù), 否則使用默認值進行計算UICollectionViewCell的布局屬性(例如rowMargin)
#pragma mark - 常見數(shù)據(jù)處理
- (CGFloat)rowMargin
{
  if ([self.delegate respondsToSelector:@selector(rowMarginInWaterflowLayout:)]) {
      return [self.delegate rowMarginInWaterflowLayout:self];
  } else {
      return MRDefaultRowMargin;
  }
}
  • 創(chuàng)建瀑布流 類似于使用UITableView
// 創(chuàng)建布局
  MRWaterflowLayout *layout = [[MRWaterflowLayout alloc] init];
  layout.delegate = self;
  
  // 創(chuàng)建CollectionView, layout一定要創(chuàng)建才能對UICollectionView進行初始化
  UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
  collectionView.backgroundColor = [UIColor whiteColor];
  collectionView.dataSource = self;
  [self.view addSubview:collectionView];

瀑布流效果

溫馨提示: 如果您喜歡, 可以前往GitHub點擊Star哦~

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末死姚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子膝藕,更是在濱河造成了極大的恐慌转晰,老刑警劉巖龟糕,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朦促,居然都是意外死亡叉信,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門于樟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來公条,“玉大人,你說我怎么就攤上這事迂曲“谐鳎” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵路捧,是天一觀的道長关霸。 經(jīng)常有香客問我,道長杰扫,這世上最難降的妖魔是什么队寇? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮涉波,結果婚禮上英上,老公的妹妹穿的比我還像新娘。我一直安慰自己啤覆,他們只是感情好苍日,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著窗声,像睡著了一般相恃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笨觅,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天拦耐,我揣著相機與錄音,去河邊找鬼见剩。 笑死杀糯,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的苍苞。 我是一名探鬼主播固翰,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼狼纬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了骂际?” 一聲冷哼從身側(cè)響起疗琉,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎歉铝,沒想到半個月后盈简,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡太示,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年柠贤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片先匪。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡种吸,死狀恐怖弃衍,靈堂內(nèi)的尸體忽然破棺而出呀非,到底是詐尸還是另有隱情,我是刑警寧澤镜盯,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布岸裙,位于F島的核電站,受9級特大地震影響速缆,放射性物質(zhì)發(fā)生泄漏降允。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一艺糜、第九天 我趴在偏房一處隱蔽的房頂上張望剧董。 院中可真熱鬧,春花似錦破停、人聲如沸翅楼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毅臊。三九已至,卻和暖如春黑界,著一層夾襖步出監(jiān)牢的瞬間管嬉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工朗鸠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蚯撩,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓烛占,卻偏偏與公主長得像胎挎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容