IOS 瀑布流UICollectionView實現,tableview實現瀑布流

來源:互聯網
上載者:User

IOS 瀑布流UICollectionView實現,tableview實現瀑布流
IOS 瀑布流UICollectionView實現

在實現瀑布流之前先來看看瀑布流的雛形(此方法的雛形 UICollectionView)

對於UICollectionView我們有幾點注意事項

  • 它和tableView不一樣,ContentView的內容完全需要我們自己去添加。
  • 它與tableview相比,他的初始化需要FlowLayout並且大部分操作在其上。
  • UIcollectionView的實用性極強,雖然有時他並不是最好的解決方案,但是它可以很靈活的實現各種效果。

圖(一)

,模擬器上展示的是很多方格,但是值得注意的是他們是有規則的。

雖然看上去很整潔但是並不美觀。

我們所說的要實現瀑布流就是要實現它的不整潔,但是規律(這裡我說的是規律)

正題

前面說了UIcollectionView的大部分操作在FlowLayout上,當然也包括格局部署。

為了實現瀑布流我們所要實現的便是改變他的格局部署。

在寫代碼前先確定一下實現思想。
  • 需要什嗎???
    • 首先我們需要確定瀑布流的顯示風格
    • 然後根據確定好的風格進行整體設計
    • 最後通過細節的處理完善代碼
      • 我們需要什麼樣的風格???
        • 我們需要的是實現將上面圖片中的布局改變為不等高的效果
        • 說的俗一點就是像名字一樣,像瀑布流水一樣
      • 整體該如何設計???
        • 整體採用與上面圖片一樣的設計方法,每個模組都是一個cell
        • 確保最上面一行的cell的y值相同(美觀)
        • 確保不不會出現一列特別長,一列特別短的效果
      • 初步細節有哪些???
        • 因為每個cell的height不同,所以我們要考慮放置的順序應該是什麼
        • 精簡代碼(這是每個項目必須注意的)
實現效果

代碼

下面是實現的代碼部分(不提供demo了 很簡單)

我在注釋中簡單介紹。

---

////  ViewController.m//  CX-瀑布流UIcollectionView實現////  Created by ma c on 16/4/8.//  Copyright © 2016年 bjsxt. All rights reserved.//#import "ViewController.h"#import "CXCollectionViewCell.h"#import "CXCollectionViewLayout.h"static NSString * identifier = @"cellID";@interface ViewController ()<UICollectionViewDataSource>//所要展示的UICollectionView@property (nonatomic, strong) UICollectionView * collectionView;@end@implementation ViewController#pragma mark - <懶載入>- (UICollectionView *)collectionView {    if (!_collectionView) {        //初始化我們自訂的flowLayout        CXCollectionViewLayout * flowLayout = [[CXCollectionViewLayout alloc]init];        //初始化collectionView        _collectionView = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:flowLayout];        //設定資料來源(collectionView的命根子)        _collectionView.dataSource = self;        //註冊我們自訂的cell        [_collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([CXCollectionViewCell class]) bundle:nil] forCellWithReuseIdentifier:identifier];    }    return _collectionView;}#pragma mark - <life>- (void)viewDidLoad {    [super viewDidLoad];    //在self.view上添加---    [self.view addSubview:self.collectionView];}#pragma mark - <UICollectionViewDataSource>//這裡返回的是item的個數 返回100- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{        return 100;}//這裡返回的是cell 我們可以在這裡進行一些簡單的操作-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{        CXCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];    //為了瀑布流的實現細節我們添加的Label        cell.label.text = [NSString stringWithFormat:@"%zd",indexPath.item];    //cell的背景色    cell.backgroundColor = [UIColor orangeColor];        return cell;}@end

---

////  CXCollectionViewLayout.m//  CX-瀑布流UIcollectionView實現////  Created by ma c on 16/4/8.//  Copyright © 2016年 bjsxt. All rights reserved.//#import "CXCollectionViewLayout.h"//瀑布流的列數static NSInteger CXcolumnCount = 3;//瀑布流的內邊距static UIEdgeInsets CXdefaultEdgeInsets = {20,15,10,15};//cell的列間距static NSInteger CXcolumnMagin = 10;//cell的行間距static NSInteger CXrowMagin = 10;@interface CXCollectionViewLayout ()//存放所有cell 的布局屬性@property (nonatomic, strong) NSMutableArray * CXattrsArray;//縮放所有列的高度@property (nonatomic, strong) NSMutableArray * CXcolumnHeights;@end@implementation CXCollectionViewLayout#pragma mark - <懶載入>- (NSMutableArray *)CXattrsArray{    if (!_CXattrsArray) {        _CXattrsArray = [NSMutableArray array];    }    return _CXattrsArray;}- (NSMutableArray *)CXcolumnHeights{    if (!_CXcolumnHeights) {        _CXcolumnHeights = [NSMutableArray array];    }    return _CXcolumnHeights;}#pragma mark - <準備布局>//準備布局(布局前自動執行)- (void) prepareLayout{    //重寫此方法一定要記得super    [super prepareLayout];        //在實際操作中我們的資料並不會固定不變的,因此我們每次布局前最好要清空之前儲存的屬性    //清空存放所有列的高度    //清空存放所有cell的不去屬性    [self.CXcolumnHeights removeAllObjects];    [self.CXattrsArray removeAllObjects];    //首先為第一行的cell附高度    for (NSInteger i = 0; i < CXcolumnCount; i ++) {        //數組裡只能存放對象        [self.CXcolumnHeights addObject:@(CXdefaultEdgeInsets.top)];    }    //下面開始建立每一個cell的布局屬性 並且添加到儲存cell布局屬性的數組中    //cell總個數 因為這裡只要一個section    NSInteger count = [self.collectionView numberOfItemsInSection:0];    for (NSInteger i = 0; i < count; i ++) {        // 建立位置 即indexPath        NSIndexPath * indexPath = [NSIndexPath indexPathForItem:i inSection:0];        //擷取indexPath對應的cell布局屬性        UICollectionViewLayoutAttributes * attributes = [self layoutAttributesForItemAtIndexPath:indexPath];        //把擷取到的布局屬性添加到數組中        [self.CXattrsArray addObject:attributes];    }    //準備布局的工作到這裡就結束了}//返回所有cell布局屬性 及整體cell 的排布- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{    return self.CXattrsArray;}//返回cell 的布局屬性- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{    //建立布局屬性    UICollectionViewLayoutAttributes * CXattributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];        //擷取collectionView 的寬    CGFloat collectionViewWidth = self.collectionView.frame.size.width;    //下面的一部分是擷取cell的frame(布局屬性)    CGFloat width;    CGFloat height;    CGFloat X;    CGFloat Y;    //擷取width    width = (collectionViewWidth - CXdefaultEdgeInsets.left - CXdefaultEdgeInsets.right - (CXcolumnCount - 1) * CXcolumnMagin) / CXcolumnCount;    //擷取height    //在實際開發中heigh並不是真正的隨機 而是根據資料來決定height 在這裡展示初步的介紹其原理 因此採用大於100小於150的隨機數    height = 100 + arc4random_uniform(50);    //擷取X (瀑布流的實現重點就在cell的X,Y值擷取)    //設定一個列數的中間變數    NSInteger tempColumn = 0;    //設定高度小的中間變數 在這裡我們把第0列的高度給他,這樣可以減少迴圈次數,提高效率    CGFloat minColumnHeight = [self.CXcolumnHeights[0] doubleValue];    for (NSInteger i = 1; i < CXcolumnCount; i ++) {        if (minColumnHeight > [self.CXcolumnHeights[i] doubleValue]) {            minColumnHeight = [self.CXcolumnHeights[i] doubleValue];            tempColumn = i;        }    }    X = CXdefaultEdgeInsets.left + (width + CXcolumnMagin) * tempColumn;    //擷取Y    Y = minColumnHeight;    if (Y != CXdefaultEdgeInsets.top) {        Y += CXrowMagin;    }    //設定cell的frame    CXattributes.frame = CGRectMake(X, Y, width, height);    //更新高度最矮的那列的高度    self.CXcolumnHeights[tempColumn] = @(CGRectGetMaxY(CXattributes.frame));        return CXattributes;}//返回collegeView的Content的大小- (CGSize)collectionViewContentSize{    //雖說返回的是大小,但是我們這裡主要的是height    CGFloat maxColumnHeight = [self.CXcolumnHeights[0] doubleValue];    for (NSInteger i = 1; i < CXcolumnCount; i++) {        CGFloat columnHeight = [self.CXcolumnHeights[i] doubleValue];                if (maxColumnHeight < columnHeight) {            maxColumnHeight = columnHeight;        }    }    return CGSizeMake(0, maxColumnHeight + CXdefaultEdgeInsets.bottom);    }@end

到此為止瀑布流的實現也就結束了。

在這裡說明幾點值得注意的地方。

  • 瀑布流中的cell排布順勢是根據當前列的高度有關的(例如:如果當前第三列是最短的,但是按正常情況下cell應該排在第一列,那麼這個時候,新的cell會排在第三列,這是為了避免某一列高度特別長或某一列的高度特別短)
  • 在實際應用中通常cell的大小是根據資料的來處理的
  • UIcollectionView的content的高度是不確定的,因此我們要根據內容設定高度。
  • 當涉及到重新整理的時候我們要注意cell的布局屬性是否在新資料到來前清空了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.