<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          iOS UICollectionView 全解

          共 10284字,需瀏覽 21分鐘

           ·

          2017-07-28 05:58

          什么是UICollectionView?

          UICollectionView是一種新的數(shù)據(jù)展示方式,簡單來說可以把他理解成多列的UITableView。它有許多與UITableView相同的地方,例如:數(shù)據(jù)源、代理等接口等。既然,UITableView有這么多的相似之處,為什么還要學(xué)習(xí)CollectionView呢?作為一個(gè)獨(dú)立的控件,CollectionView有著自己獨(dú)特的布局特性,這一點(diǎn)拉開了兩個(gè)控件的差距,所以學(xué)習(xí)UIcollectionView還是非常有必要的。

          UICollectionView 組成

          image.png.jpeg

          如圖:你看到的就是一個(gè)最簡單的UICollectionView,它包含:Cells、Supplementary Views、Decoration Views。

          1.Cells :用于展示內(nèi)容的主體,cell的尺寸和內(nèi)容可以各不相同。這個(gè)下面會(huì)詳細(xì)介紹。
          2.Supplementary Views : 追加視圖,類似于UITableView每個(gè)Seciton的Header View 或者Footer View,用來標(biāo)記Section的View
          3.Decoration Views :裝飾視圖,完全跟數(shù)據(jù)沒有關(guān)系的視圖,負(fù)責(zé)給cell 或者supplementary Views添加輔助視圖用的,靈活性較強(qiáng)。
          不管多么復(fù)雜的UIcollectionView都是由著三個(gè)部件組成的。

          實(shí)現(xiàn)一個(gè)簡單的UICollectionView

          相信如果你對UITableView有所了解的話,實(shí)現(xiàn)一個(gè)UICollectionView,其實(shí)和UITableView沒有多大的區(qū)別,它們同樣是由dataSource和delegate模式設(shè)計(jì)的:dataSource為View提供數(shù)據(jù)源,告訴View要顯示什么樣的數(shù)據(jù),delegate提供一些樣式的小細(xì)節(jié)以及用戶交互的響應(yīng)。但是值得一提的是要想初始化一個(gè)UICollectionView,一定要為它提供一個(gè)布局,即:UICollectionViewLayout對象,改對象定義了CollectionView的一些獨(dú)特的布局,后面會(huì)詳細(xì)的介紹。

          UICollectionViewDataSource

          • section數(shù)量 :numberOfSectionsInCollectionView:
            某個(gè)section中多少個(gè)item:collectionView:numberOfItemsInSection:
          • 對于某個(gè)位置的顯示什么樣的cell:collectionView:cellForItemAtIndexPath:
          • 對于某個(gè)section顯示什么樣的supplementary View:collectionView:viewForSupplementaryElementOfKind:atIndexPath:
            對于Decoration Views,提供的方法并不在UICollectionViewDataSource中,而是在UICollectionViewLayout中(因?yàn)樗鼉H僅跟視圖相關(guān),而與數(shù)據(jù)無關(guān))。

          UICollectionView子視圖重用

          與UITableView一樣,避免不斷的生成和銷毀對象,UICollectionView對于view的重用是必須的。但是我們發(fā)現(xiàn)在UIcollectionview中不僅僅是cell的重用,Supplementary View和Decoration View也是可以并且應(yīng)當(dāng)被重用的,細(xì)心的朋友可以發(fā)現(xiàn),UIcollectionViewCell繼承自UICollectionReusableView,而在collectionView:viewForSupplementaryElementOfKind:atIndexPath:這個(gè)方法的返回類型是:UICollectionReusableView,其實(shí)蘋果給UIcollectionview中的所有視圖都來自一個(gè)可重用的基類,就是UICollectionReusableView,所以自定義Supplementary View和Decoration View也是繼承者個(gè)類為基礎(chǔ),來構(gòu)建自己的視圖。

          • 注冊自定義視圖
          • registerClass:forCellWithReuseIdentifier:
          • registerNib:forCellWithReuseIdentifier:
          • registerClass:forSupplementaryViewOfKind:withReuseIdentifier:
          • registerNib:forSupplementaryViewOfKind:withReuseIdentifier:
            得到對應(yīng)的視圖
          • dequeueReusableCellWithReuseIdentifier:forIndexPath:
          • dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:
            其中SupplementaryViewOfKind:參數(shù)的類型是一個(gè)字符串常量,UICollectionElementKindSectionHeader/UICollectionElementKindSectionFooter該常量的定義UICollectionViewDelegateFlowLayout類中。

          UICollectionViewDelegate

          和數(shù)據(jù)無關(guān)的view的外形,用戶的交互什么的,都是UICollectionViewDelegate來負(fù)責(zé)

          • cell的高亮
          • cell的選中狀態(tài)
          • 可以支持長安后的菜單
          • 在用戶交互上UIcollectionview做了很多細(xì)節(jié)的處理,每個(gè)cell有獨(dú)立的高亮、選中事件的delegate,開發(fā)者可以監(jiān)聽到的事件變得多起來,當(dāng)用戶點(diǎn)擊一個(gè)cell的時(shí)候,會(huì)按以下的流程delegate詢問(這是UIcollectionViewDelegate API中給出的):

          (when the touch begins)

          • 1、-collectionView:shouldHighlightItemAtIndexPath:是否應(yīng)該高亮?
          • 2、-collectionView:didHighlightItemAtIndexPath:如果1返回YES,執(zhí)行,否則不執(zhí)行
            (when the touch lifts)
          • 3、-collectionView:shouldSelectItemAtIndexPath: or -collectionView:shouldDeselectItemAtIndexPath:如果1返回NO這里不再詢問詢問是否選中,
          • 4、-collectionView:didSelectItemAtIndexPath: or -collectionView:didDeselectItemAtIndexPath:如果3中返回選中,調(diào)用選中
          • 5、-collectionView:didUnhighlightItemAtIndexPath:如果1返回YES,那么會(huì)調(diào)用取消高亮
            在UIcollectionview中分別有selected和highlighted屬性控制狀態(tài)。

          UICollectionViewCell

          相對于UItableViewCell而言,UIcollectionViewCell沒有那么多樣式。UIcollectionViewCell不存在所謂的style,也沒有titleLabel和內(nèi)置的imageView屬性,UIcollectionViewCell的結(jié)構(gòu)上相對比較簡單,由下至上:

          • cell :本身作為的View,這里應(yīng)該就是UICollectionReusableView
          • backgroundView :用作cell背景的視圖,設(shè)置背景圖片等。
          • selectedBackgroundView :cell被選中的背景視圖
          • contentView :內(nèi)容視圖,自定義的cell時(shí)應(yīng)該將內(nèi)容放在這個(gè)View上

          UIcollectionView有一個(gè)小細(xì)節(jié):被選中的cell的自動(dòng)變化,所有的cell中的子View,也包括contentView中的子View,當(dāng)cell被選中是,會(huì)自動(dòng)去查找view是否有被選中狀態(tài)下的改變,如果在contentView中有一個(gè)imageView的selected和normal狀態(tài)下的圖片是不同的,那么選中cell這張圖片也會(huì)從normal變成selected,不需要添加代碼。

          UICollectionView 布局 UICollectionViewLayout

          UICollectionViewLayout是UICollectionView特有的,是UICollectionView的精髓所在,它負(fù)責(zé)將每個(gè)cell、supplementary view、decoration view進(jìn)行組合,為它們設(shè)置各自的屬性,包括:位置、大小、透明度、層級關(guān)系、形狀等。UICollectionViewLayout決定了,UICollectionView是如何顯示在界面上,從UICollectionView初始化必須要一個(gè)UICollectionViewLayout也可以看得出來,Layout對于UICollectionView的最要性。

          UICollectionViewFlowLayout 流水布局

          蘋果為我們設(shè)計(jì)了一套非常靈活、通用的Layout,就是UICollectionViewFlowLayout流水布局,也叫線性布局。UICollectionViewFlowLayout屬性:

          • CGSize itemSize:它定義了每一個(gè)item的大小,通過itemSize可以快捷給每一個(gè)cell設(shè)置一樣的大小,如果你想到不同的尺寸,-collectionView:layout:sizeForItemAtIndexPath:來給每一個(gè)item指定不同的尺寸。
          • CGFloat minimumLineSpacing:最小行間隔,同樣你也可以通過-* collectionView:minimumLineSpacingForSectionAtIndex:方法來個(gè)沒一行設(shè)置不同的行間距
          • CGFloat minimumInteritemSpacing:最小cell之間的距離,同上都是可以通過-collectionView:minimumInteritemSpacingForSectionAtIndex:特定的方法,頂?shù)椎骄唧w的行和item之間的間距的,非常的靈活。
          • UIEdgeInsets sectionInset:組內(nèi)邊距,設(shè)置UIcollectionView整體的組內(nèi)邊距,同上有特定方法-collectionView:insetForSectionAtIndex:設(shè)置具體的邊距
          • CGSize headerReferenceSize:設(shè)置supplementary header View的大小-collectionView:referenceSizeForHeaderInSection:
          • CGSize footerReferenceSize:設(shè)置supplementary header View的大小-collectionView:referenceSizeForFooterInSection:
          • UICollectionViewScrollDirection scrollDirection:設(shè)置UIcollectionView的滾動(dòng)方向

          UICollectionViewFlowLayout方法:

          // 1、準(zhǔn)備布局,布局初始化一般在這里進(jìn)行
          - (void)prepareLayout;
          
          // 每當(dāng)collectionView邊界改變時(shí)便調(diào)用這個(gè)方法詢問 是否 重新初始化布局 是則調(diào)用prepareLayout準(zhǔn)備布局
          - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;
          
          // 2、初始化布局時(shí)調(diào)用,返回在一定區(qū)域內(nèi),每個(gè)cell和Supplementary和Decoration的布局屬性
          - (NSArray *)layoutAttributesForElementsInRect: (CGRect)rect;
          
          // 當(dāng)滾動(dòng)停止時(shí),會(huì)調(diào)用該方法確定collectionView滾動(dòng)到的位置
          - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset   withScrollingVelocity:(CGPoint)velocity;
          在使用UICollectionViewFlowLayout布局的時(shí)候,有時(shí)會(huì)有特別的需求,比如:當(dāng)一個(gè)cell滑動(dòng)到屏幕中點(diǎn)的時(shí)候放大,并且當(dāng)我停止滑動(dòng)時(shí),能夠?qū)㈦x屏幕最近的cell居中。這四個(gè)方法就能輕松的完成這樣的事。

          UICollectionViewLayoutAttributes 布局屬性

          在了解這個(gè)類之前,我們得先疏通一下,UIcollectionView的布局方式,首先我們之前一直提,UIcollectionView的初始化必須有一個(gè)UICollectionViewLayout,也就是我們說的,必須要有一個(gè)布局格式樣式,那么一個(gè)UIcollectionView有那么多的cell、supplementary View、decoration View,UIcollectionViewLayout是如何進(jìn)行布局顯示的呢?原來從UIcollectionViewLayout開始加載內(nèi)容的時(shí)候,便默默的做了很多事:首先是去調(diào)用 1 準(zhǔn)備布局,然后根據(jù)當(dāng)前屏幕所處位置的合適rect,得到每一個(gè)視圖的UICollectionViewLayoutAttributes屬性,然后在把視圖按UICollectionViewLayoutAttributes中的屬性描述設(shè)置視圖具體的center、size等等,期間也會(huì)去調(diào)用其他方法去確定一些間距。所以UICollectionViewLayoutAttributes是每個(gè)視圖決定性的布局的屬性。

          • CGRect frame 布局視圖的frame簡單明了
          • CGPoint center 視圖中心點(diǎn)
          • CGSize size 視圖尺寸
          • CATransform3D transform3D 這個(gè)屬性可以用來做酷炫的3D動(dòng)畫
          • CGAffineTransform transform 轉(zhuǎn)場屬性
          • CGFloat alpha 透明度
          • NSInteger zIndex 層級,數(shù)字越大,層級越高(最上面)。
          • NSIndexPath *indexPath 如果是cell有對應(yīng)的indexPath
          • UICollectionElementCategory representedElementCategory 視圖標(biāo)記,是cell還是supplementary View或者decoration View
          • registerClass:forDecorationViewOfKind: 注冊decoration View
          • registerNib:forDecorationViewOfKind:
          • +(instancetype)layoutAttributesForDecorationViewOfKind:(NSString )decorationViewKind withIndexPath:(NSIndexPath )indexPath 這個(gè)類方法是decoration View布局的來源
          • -(nullable UICollectionViewLayoutAttributes )layoutAttributesForDecorationViewOfKind:(NSString )elementKind atIndexPath:(NSIndexPath *)indexPath 與上一個(gè)方法結(jié)合得到decoration View布局

          UICollectionViewLayout 自定義布局

          由于系統(tǒng)給我們設(shè)計(jì)的流水局在實(shí)現(xiàn)和細(xì)節(jié)處理上,幫我們做了很多事,所以完全的自定義布局是挺麻煩,并且要考慮到各種細(xì)節(jié)的。在UIcollectionViewLayout頭文件中,蘋果給我提供很多特定的方法,以供我們自己布局,有僅僅關(guān)于布局的、有關(guān)于刪除插入item的布局、有關(guān)于移動(dòng)item的布局。方法分的很細(xì),我們只了解基本的布局、刪除和插入布局等。

          • @interface UICollectionViewLayout (UISubclassingHooks) 這個(gè)擴(kuò)展類中,都是用來布局UIcollectionView子視圖的
          • @interface UICollectionViewLayout (UIUpdateSupportHooks) 用來布局刪除插入動(dòng)作
          • @interface UICollectionViewLayout (UIReorderingSupportHooks) 移動(dòng)動(dòng)作布局

          UISubclassingHooks

          這個(gè)擴(kuò)展類里面的方法,上面流水布局的代碼處已經(jīng)給列舉出來,就不多說了

          UIUpdateSupportHooks

          在UIcollectionView中刪除或者插入item時(shí),建議使用下面的方式:

          [self.collectionView performBatchUpdates:^{
              [self.collectionView deleteItemsAtIndexPaths:@[pinchIndexPath]];
          } completion:nil];
          [self.collectionView performBatchUpdates:^{
              [self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
          } completion:nil];  

          值得一說的是,在對UIcollectionView插入和刪除操作是,不管使用的是上面的更新方式還是reloadData,collectionView都不會(huì)刷新全部的cell,具體原因本人也不是很清楚,多說無益,下面上刪除、插入的代碼:

          /*  在insert或者delete之前,prepareForCollectionViewUpdates:會(huì)調(diào)用,
              可以使用這個(gè)方法來完成 添加/ 刪除的預(yù)處理,將要?jiǎng)h除或者插入的indexPath保存
          */
          - (void)prepareForCollectionViewUpdates:(NSArray *)updateItems {
          
              // Keep track of insert and delete index paths
              [super prepareForCollectionViewUpdates:updateItems];
          
              self.deleteIndexPaths = [NSMutableArray array];
              self.insertIndexPaths = [NSMutableArray array];
          
              for (UICollectionViewUpdateItem *update in updateItems) {
                  if (update.updateAction == UICollectionUpdateActionDelete) {
                      [self.deleteIndexPaths addObject:update.indexPathBeforeUpdate];
          
                  }else if (update.updateAction == UICollectionUpdateActionInsert) {
          
                      [self.insertIndexPaths addObject:update.indexPathAfterUpdate];
                  }
              }
          }
          
          // 更新結(jié)束后調(diào)用 這個(gè)方法在 performBatchUpdates:completion: complete的Block之前調(diào)用
          - (void)finalizeCollectionViewUpdates {
              [super finalizeCollectionViewUpdates];
              //  釋放insert and delete index paths
              self.deleteIndexPaths = nil;
              self.insertIndexPaths = nil;
          }
          
          /**
              這兩個(gè)方法是成對出現(xiàn)的,一個(gè)是在在屏幕上出現(xiàn)之前調(diào)用,一個(gè)是在屏幕上出現(xiàn)之后調(diào)用
              在[collecView reloadData]或者performBatchUpdates:completion:調(diào)用的時(shí)候
              只要是有刷新的效果,他們就會(huì)被調(diào)用多次,視圖不斷的消失(失效,被摧毀)出現(xiàn)(重組 被創(chuàng)建或者回收利用)
           */
          // For each element on screen before the invalidation,
          - (nullable UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
              // Must call super
              UICollectionViewLayoutAttributes *attributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
          
              if ([self.insertIndexPaths containsObject:itemIndexPath]) {
                  // 只改變插入的 attributes
                  attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
          
                  // configure attributes...
                  attributes.alpha = 0;
                  attributes.center = _center;
                  attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);
              }
              return attributes;
          }
          
          // For each element on screen after the invalidation,
          - (nullable UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
              UICollectionViewLayoutAttributes *attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath];
          
              if ([self.deleteIndexPaths containsObject:itemIndexPath]) {
                  attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
                  attributes.alpha = 0;
                  attributes.center = _center;
                  attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0);
              }
              return attributes;
          }

          UICollectionViewUpdateItem

          這個(gè)類是UIcollectionView更新布局的時(shí)候,新舊布局信息交換的媒介,它存儲了舊的布局,或者新布局。

          轉(zhuǎn)載我好朋友的一片文章,自己做了一部分的修改,挺詳細(xì)的,轉(zhuǎn)載出來大家分享一下。

          瀏覽 54
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产欧美综合一区 | 亚洲乱伦第一页 | 日日躁夜夜躁夜夜揉人人视频 | 国产黄色接吻视频网站 | 亚洲A网站 |