UICollectionView 的相關使用

簡介

  • 繼承自 UIScrowView
  • 從 iOS 6 開始引入使用的
  • Cell 只能通過注冊來確定重用標識符
  • 每個格子都是個 UICollectionViewCell
    每行顯示多少個 Cell,取決于 UICollectionView 的寬度 能容納多少 Cell

UICollectionView 和 UITableView 的比較

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

UICollectionView 既可以垂直滾動,也可以水平滾動

  • UITableView 的 Cell 是系統自動布局的,不需要自定義
  • UICollectionView 的 Cell 必須自定義布局
    在創建 UICollectionView 的時候必須傳遞一個布局參數
    系統提供并實現了一個布局樣式:UICollectionViewFlowLayout 流水布局

1. 組成結構

可見部分

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

不可見部分

  • UICollectionViewLayout 用來處理cell在屏幕上的布局

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

2. 自定義布局

布局的函數調用流程

  • 白框代表 CollectionView 在布局時使用的方法
  • 橙框代表 CollectionView 的狀態
  • 綠框代表 CollectionView 的使用者調用的方法
Paste_Image.png

簡介

  • UICollectionViewLayout 「抽象類」 會對屏幕上的 Cells 進行組織布局

首先要繼承

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

I. 預先設置布局樣式

作用

  • prepareLayout 用來做一些初始化操作
  • prepareLayout 執行前,collectionView 相關的尺寸等已經確定下來,供 prepareLayout 使用
// 注意:重寫本方法時,必須調用父類方法
- (void)prepareLayout;

II. 在給定矩形范圍內設置布局屬性

作用

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

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

III. 確保每次滾動時重新布局

作用

  • 表示 collectionView 滾動時「顯示的范圍發生改變時」,是否廢棄當前的布局
  • 一旦廢棄當前的布局,就會依次調用 prepareLayoutlayoutAttributesForElementsInRect: 方法
// 默認 返回 NO
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;

IV. 確定滾動結束后的布局

作用

  • 滑動 collectionView 松開后調用
  • 返回 collectionView 停止滾動時最終的偏移量 contentOffset
// proposedContentOffset:collectionView 停止滾動時最終的偏移量
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset; 

// velocity:滾動速率,通過這個參數可以了解滾動的方向
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity; 

3. 總體步驟

原理

  • UICollectionView 向 UICollectionViewLayout 詢問布局
    詢問時,layout 對象會創建 UICollectionViewLayoutAttributes 實例
  • 1 個 UICollectionViewLayoutAttributes 對象管理著 1 個對應的 item layout 相關信息「一對一關系」

步驟

  • 注冊 Cell「告訴 collectionView 將來創建那種標識的 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;
}
  • 重寫 init 方法,創建布局參數「必須傳入 非空布局,否則會報錯」
// UICollectionViewFlowLayout 流水布局的內部成員屬性有以下:
@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; // 滾動方向「默認豎直方向」
@property (nonatomic) CGSize headerReferenceSize; // 每一組 header的大小
@property (nonatomic) CGSize footerReferenceSize; // 每一組 footer的大小
@property (nonatomic) UIEdgeInsets sectionInset;  // UICollectionView 四周的內邊距

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

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

@required

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

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

// 點擊了一個 Cell 后調用
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容