UICollectionView 的相關(guān)使用

簡(jiǎn)介

  • 繼承自 UIScrowView
  • 從 iOS 6 開(kāi)始引入使用的
  • Cell 只能通過(guò)注冊(cè)來(lái)確定重用標(biāo)識(shí)符
  • 每個(gè)格子都是個(gè) UICollectionViewCell
    每行顯示多少個(gè) Cell,取決于 UICollectionView 的寬度 能容納多少 Cell

UICollectionView 和 UITableView 的比較

  • UITableViewController 的 self.view == self.tableview;
    UICollectionViewController 的 self.view != self.collectionView;
  • UITableView 的滾動(dòng)方式只能是垂直方向

UICollectionView 既可以垂直滾動(dòng),也可以水平滾動(dòng)

  • UITableView 的 Cell 是系統(tǒng)自動(dòng)布局的,不需要自定義
  • UICollectionView 的 Cell 必須自定義布局
    在創(chuàng)建 UICollectionView 的時(shí)候必須傳遞一個(gè)布局參數(shù)
    系統(tǒng)提供并實(shí)現(xiàn)了一個(gè)布局樣式:UICollectionViewFlowLayout 流水布局

1. 組成結(jié)構(gòu)

可見(jiàn)部分

  • UICollectionView 內(nèi)容顯示的主視圖:類(lèi)似于 UITableView
  • UICollectionViewCell 用于展示內(nèi)容的主體:對(duì)于不同的 Cell 可以指定不同的尺寸和內(nèi)容
  • Supplementary View 附加視圖:可以理解為 UITableView 每個(gè) Section 的 HeaderView 和 FooterView
  • Decoration View 裝飾視圖:這是每個(gè) section 的背景視圖,用于裝飾該 section

不可見(jiàn)部分

  • UICollectionViewLayout 用來(lái)處理cell在屏幕上的布局

使用一系列的代理方法在 UICollectionView 上約束 Cell 的擺放,而且布局效果可以在運(yùn)行時(shí),隨時(shí)改變

2. 自定義布局

布局的函數(shù)調(diào)用流程

  • 白框代表 CollectionView 在布局時(shí)使用的方法
  • 橙框代表 CollectionView 的狀態(tài)
  • 綠框代表 CollectionView 的使用者調(diào)用的方法
Paste_Image.png

簡(jiǎn)介

  • UICollectionViewLayout 「抽象類(lèi)」 會(huì)對(duì)屏幕上的 Cells 進(jìn)行組織布局

首先要繼承

  • 繼承 UICollectionViewLayout 或 UICollectionViewFlowLayout 流水布局
  • 如果 繼承 UICollectionViewLayout,要實(shí)現(xiàn)切換布局功能時(shí)必須實(shí)現(xiàn) layoutAttributesForItemAtIndexPath: 方法
  • layoutAttributesForItemAtIndexPath: 方法中執(zhí)行 prepareLayout 方法的布局方式
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

I. 預(yù)先設(shè)置布局樣式

作用

  • prepareLayout 用來(lái)做一些初始化操作
  • prepareLayout 執(zhí)行前,collectionView 相關(guān)的尺寸等已經(jīng)確定下來(lái),供 prepareLayout 使用
// 注意:重寫(xiě)本方法時(shí),必須調(diào)用父類(lèi)方法
- (void)prepareLayout;

II. 在給定矩形范圍內(nèi)設(shè)置布局屬性

作用

  • 當(dāng) collectionView 滾動(dòng)時(shí)調(diào)用該方法
  • 1 個(gè) Cell 對(duì)應(yīng) 1 個(gè) UICollectionViewLayoutAttributes 對(duì)象
  • 返回值 UICollectionViewLayoutAttributes 對(duì)象
    決定了 Rect 范圍內(nèi) Cell 的布局方式「frame 等」
    決定了 Supplementary View、Decoration View 的布局方式
// UICollectionViewLayoutAttributes 的屬性
@property (nonatomic) CGPoint center;   // view 在 CollectionView 的坐標(biāo)系統(tǒng)中的 中心
@property (nonatomic) CGRect  frame;    // view 在 CollectionView 的坐標(biāo)系統(tǒng)中的 具體位置
@property (nonatomic) CGSize  size;     // view 的大小
@property (nonatomic) CGRect  bounds;   // view 的尺寸
@property (nonatomic) CGFloat   alpha;  // 透明度
@property (nonatomic) NSInteger zIndex; // 子視圖的層級(jí)「默認(rèn) 0」
@property (nonatomic) CATransform3D transform3D;    // 用來(lái)旋轉(zhuǎn),縮放的屬性
@property (nonatomic) CGAffineTransform transform;  // 用來(lái)形裝改變
@property (nonatomic, getter=isHidden) BOOL hidden; // view 是否隱藏「如果隱藏 view 可能會(huì)不產(chǎn)生」

// rect:和 collectionView 的坐標(biāo)系一致,控制 collectionView 部分內(nèi)容顯示在屏幕上的矩形大小
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

III. 確保每次滾動(dòng)時(shí)重新布局

作用

  • 表示 collectionView 滾動(dòng)時(shí)「顯示的范圍發(fā)生改變時(shí)」,是否廢棄當(dāng)前的布局
  • 一旦廢棄當(dāng)前的布局,就會(huì)依次調(diào)用 prepareLayout、layoutAttributesForElementsInRect: 方法
// 默認(rèn) 返回 NO
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;

IV. 確定滾動(dòng)結(jié)束后的布局

作用

  • 滑動(dòng) collectionView 松開(kāi)后調(diào)用
  • 返回 collectionView 停止?jié)L動(dòng)時(shí)最終的偏移量 contentOffset
// proposedContentOffset:collectionView 停止?jié)L動(dòng)時(shí)最終的偏移量
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset; 

// velocity:滾動(dòng)速率,通過(guò)這個(gè)參數(shù)可以了解滾動(dòng)的方向
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity; 

3. 總體步驟

原理

  • UICollectionView 向 UICollectionViewLayout 詢問(wèn)布局
    詢問(wèn)時(shí),layout 對(duì)象會(huì)創(chuàng)建 UICollectionViewLayoutAttributes 實(shí)例
  • 1 個(gè) UICollectionViewLayoutAttributes 對(duì)象管理著 1 個(gè)對(duì)應(yīng)的 item layout 相關(guān)信息「一對(duì)一關(guān)系」

步驟

  • 注冊(cè) Cell「告訴 collectionView 將來(lái)創(chuàng)建那種標(biāo)識(shí)的 Cell」
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellID"];
  • 從緩存池中取出 Cell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];

    return cell;
}
  • 重寫(xiě) init 方法,創(chuàng)建布局參數(shù)「必須傳入 非空布局,否則會(huì)報(bào)錯(cuò)」
// UICollectionViewFlowLayout 流水布局的內(nèi)部成員屬性有以下:
@property (nonatomic) CGFloat minimumLineSpacing;      // Cell 之間的垂直間距
@property (nonatomic) CGFloat minimumInteritemSpacing; // Cell 之間的水平間距
@property (nonatomic) CGSize itemSize;                 // Cell 的尺寸
@property (nonatomic) CGSize estimatedItemSize NS_AVAILABLE_IOS(8_0);
@property (nonatomic) UICollectionViewScrollDirection scrollDirection; // 滾動(dòng)方向「默認(rèn)豎直方向」
@property (nonatomic) CGSize headerReferenceSize; // 每一組 header的大小
@property (nonatomic) CGSize footerReferenceSize; // 每一組 footer的大小
@property (nonatomic) UIEdgeInsets sectionInset;  // UICollectionView 四周的內(nèi)邊距

- (id)init {
    // 流水布局
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.minimumLineSpacing = 10;
    layout.sectionInset = UIEdgeInsetsMake(layout.minimumLineSpacing, 0, 0, 0);
    return [super initWithCollectionViewLayout:layout];
}
  • 實(shí)現(xiàn)數(shù)據(jù)源方法
@optional

// 返回每個(gè)組的 Cell 的數(shù)量「每個(gè)組的數(shù)量相同時(shí)使用」
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;

@required

// 返回 給定組的 Cell 的數(shù)量
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;

// 返回 給定組號(hào)和組中序號(hào) 的 Cell 對(duì)象
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
  • 實(shí)現(xiàn)代理方法「Optional」
@optional // 所有代理方法都是可選的

// 點(diǎn)擊了一個(gè) Cell 后調(diào)用
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容