//聯(lián)系人:石虎? QQ: 1224614774昵稱:嗡嘛呢叭咪哄
什么是UICollectionView
UICollectionView是一種新的數(shù)據(jù)展示方式,簡單來說可以把他理解成多列的UITableView(請一定注意這是UICollectionView的最最簡單的形式)。如果你用過iBooks的話质和,可能你還對書架布局有一定印象:一個虛擬書架上放著你下載和購買的各類圖書,整齊排列。其實這就是一個UICollectionView的表現(xiàn)形式忍啸,或者iPad的iOS6中的原生時鐘應用中的各個時鐘,也是UICollectionView的最簡單的一個布局履植,如圖:
最簡單的UICollectionView就是一個GridView吊骤,可以以多列的方式將數(shù)據(jù)進行展示。標準的UICollectionView包含三個部分静尼,它們都是UIView的子類:
* Cells 用于展示內容的主體白粉,對于不同的cell可以指定不同尺寸和不同的內容,這個稍后再說
* Supplementary Views 追加視圖 如果你對UITableView比較熟悉的話鼠渺,可以理解為每個Section的Header或者Footer鸭巴,用來標記每個section的view
* Decoration Views 裝飾視圖 這是每個section的背景,比如iBooks中的書架就是這個
不管一個UICollectionView的布局如何變化拦盹,這三個部件都是存在的鹃祖。再次說明,復雜的UICollectionView絕不止上面的幾幅圖普舆,關于較復雜的布局和相應的特性恬口,我會在本文稍后和下一篇筆記中進行一些深入。
實現(xiàn)一個簡單的UICollectionView
先從最簡單的開始沼侣,UITableView是iOS開發(fā)中的非常非常非常重要的一個類祖能,相信如果你是開發(fā)者的話應該是對這個類非常熟悉了。實現(xiàn)一個UICollectionView和實現(xiàn)一個UITableView基本沒有什么大區(qū)別蛾洛,它們都同樣是datasource和delegate設計模式的:datasource為view提供數(shù)據(jù)源养铸,告訴view要顯示些什么東西以及如何顯示它們,delegate提供一些樣式的小細節(jié)以及用戶交互的相應轧膘。因此在本節(jié)里會大量對比collection view和table view來進行說明钞螟,如果您還不太熟悉table view的話,也是個對照著復習的好機會谎碍。
UICollectionViewDataSource
* section的數(shù)量 -numberOfSectionsInCollection:
* 某個section里有多少個item -collectionView:numberOfItemsInSection:
* 對于某個位置應該顯示什么樣的cell -collectionView:cellForItemAtIndexPath:
實現(xiàn)以上三個委托方法鳞滨,基本上就可以保證CollectionView工作正常了。當然蟆淀,還有提供Supplementary View的方法
* collectionView:viewForSupplementaryElementOfKind:atIndexPath:
對于Decoration Views拯啦,提供方法并不在UICollectionViewDataSource中闽晦,而是直接在UICollectionViewLayout類中的(因為它僅僅是視圖相關,而與數(shù)據(jù)無關)提岔,放到稍后再說。
關于重用
為了得到高效的View笋敞,對于cell的重用是必須的碱蒙,避免了不斷生成和銷毀對象的操作,這與在UITableView中的情況是一致的夯巷。但值得注意的時赛惩,在UICollectionView中,不僅cell可以重用趁餐,Supplementary View和Decoration View也是可以并且應當被重用的喷兼。在iOS5中,Apple對UITableView的重用做了簡化后雷,以往要寫類似這樣的代碼:
1
2
3
4
5
6 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MY_CELL_ID"];
if (!cell) //如果沒有可重用的cell季惯,那么生成一個 {
cell = [[UITableViewCell alloc] init];
}
//配置cell,blablabla
return cell;
而如果我們在TableView向數(shù)據(jù)源請求數(shù)據(jù)之前使用-registerNib:forCellReuseIdentifier:方法為@“MY_CELL_ID”注冊過nib的話臀突,就可以省下每次判斷并初始化cell的代碼勉抓,要是在重用隊列里沒有可用的cell的話,runtime將自動幫我們生成并初始化一個可用的cell候学。
這個特性很受歡迎藕筋,因此在UICollectionView中Apple繼承使用了這個特性,并且把其進行了一些擴展梳码。使用以下方法進行注冊:
* -registerClass:forCellWithReuseIdentifier:
* -registerClass:forSupplementaryViewOfKind:withReuseIdentifier:
* -registerNib:forCellWithReuseIdentifier:
* -registerNib:forSupplementaryViewOfKind:withReuseIdentifier:
相比UITableView有兩個主要變化:一是加入了對某個Class的注冊隐圾,這樣即使不用提供nib而是用代碼生成的view也可以被接受為cell了;二是不僅只是cell掰茶,Supplementary View也可以用注冊的方法綁定初始化了暇藏。在對collection view的重用ID注冊后,就可以像UITableView那樣簡單的寫cell配置了:
1
2
3
4
5
6 -(UICollectionView*)collectionView:(UICollectionView*)cvcellForItemAtIndexPath:(NSIndexPath*)indexPath{
MyCell*cell=[cvdequeueReusableCellWithReuseIdentifier:@”MY_CELL_ID”];
// Configure the cell's content
cell.imageView.image=...
returncell;
}
需要吐槽的是濒蒋,對collection view叨咖,取重用隊列的方法的名字和UITableView里面不一樣了,在Identifier前面多加了Reuse五個字母啊胶,語義上要比以前清晰甸各,命名規(guī)則也比以前嚴謹了..不知道Apple會不會為了追求完美而把UITableView中的命名不那么好的方法deprecate掉。
UICollectionViewDelegate
數(shù)據(jù)無關的view的外形啊焰坪,用戶交互啊什么的趣倾,由UICollectionViewDelegate來負責:
* cell的高亮
* cell的選中狀態(tài)
* 可以支持長按后的菜單
關于用戶交互,UICollectionView也做了改進某饰。每個cell現(xiàn)在有獨立的高亮事件和選中事件的delegate儒恋,用戶點擊cell的時候善绎,現(xiàn)在會按照以下流程向delegate進行詢問:
1. -collectionView:shouldHighlightItemAtIndexPath: 是否應該高亮?
2. -collectionView:didHighlightItemAtIndexPath: 如果1回答為是诫尽,那么高亮
3. -collectionView:shouldSelectItemAtIndexPath: 無論1結果如何禀酱,都詢問是否可以被選中?
4. -collectionView:didUnhighlightItemAtIndexPath: 如果1回答為是牧嫉,那么現(xiàn)在取消高亮
5. -collectionView:didSelectItemAtIndexPath: 如果3回答為是剂跟,那么選中cell
狀態(tài)控制要比以前靈活一些,對應的高亮和選中狀態(tài)分別由highlighted和selected兩個屬性表示酣藻。
關于Cell
相對于UITableViewCell來說曹洽,UICollectionViewCell沒有這么多花頭。首先UICollectionViewCell不存在各式各樣的默認的style辽剧,這主要是由于展示對象的性質決定的送淆,因為UICollectionView所用來展示的對象相比UITableView來說要來得靈活,大部分情況下更偏向于圖像而非文字怕轿,因此需求將會千奇百怪偷崩。因此SDK提供給我們的默認的UICollectionViewCell結構上相對比較簡單,由下至上:
* 首先是cell本身作為容器view
* 然后是一個大小自動適應整個cell的backgroundView撞羽,用作cell平時的背景
* 再其上是selectedBackgroundView环凿,是cell被選中時的背景
* 最后是一個contentView,自定義內容應被加在這個view上
這次Apple給我們帶來的好康是被選中cell的自動變化放吩,所有的cell中的子view智听,也包括contentView中的子view,在當cell被選中時渡紫,會自動去查找view是否有被選中狀態(tài)下的改變到推。比如在contentView里加了一個normal和selected指定了不同圖片的imageView,那么選中這個cell的同時這張圖片也會從normal變成selected惕澎,而不需要額外的任何代碼莉测。
UICollectionViewLayout
終于到UICollectionView的精髓了…這也是UICollectionView和UITableView最大的不同。UICollectionViewLayout可以說是UICollectionView的大腦和中樞唧喉,它負責了將各個cell捣卤、Supplementary View和Decoration Views進行組織,為它們設定各自的屬性八孝,包括但不限于:
* 位置
* 尺寸
* 透明度
* 層級關系
* 形狀
* 等等等等…
Layout決定了UICollectionView是如何顯示在界面上的董朝。在展示之前,一般需要生成合適的UICollectionViewLayout子類對象干跛,并將其賦予CollectionView的collectionViewLayout屬性子姜。關于詳細的自定義UICollectionViewLayout和一些細節(jié),我將寫在之后一篇筆記中楼入。
Apple為我們提供了一個最簡單可能也是最常用的默認layout對象哥捕,UICollectionViewFlowLayout牧抽。Flow Layout簡單說是一個直線對齊的layout,最常見的Grid View形式即為一種Flow Layout配置遥赚。上面的照片架界面就是一個典型的Flow Layout扬舒。
* 首先一個重要的屬性是itemSize绎狭,它定義了每一個item的大小税肪。通過設定itemSize可以全局地改變所有cell的尺寸,如果想要對某個cell制定尺寸患民,可以使用-collectionView:layout:sizeForItemAtIndexPath:方法御蒲。
* 間隔 可以指定item之間的間隔和每一行之間的間隔,和size類似诊赊,有全局屬性厚满,也可以對每一個item和每一個section做出設定:
* @property (CGSize) minimumInteritemSpacing
* @property (CGSize) minimumLineSpacing
* -collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
* -collectionView:layout:minimumLineSpacingForSectionAtIndex:
* 滾動方向 由屬性scrollDirection確定scroll view的方向,將影響Flow Layout的基本方向和由header及footer確定的section之間的寬度
* UICollectionViewScrollDirectionVertical
* UICollectionViewScrollDirectionHorizontal
* Header和Footer尺寸 同樣地分為全局和部分碧磅。需要注意根據(jù)滾動方向不同碘箍,header和footer的高和寬中只有一個會起作用。垂直滾動時section間寬度為該尺寸的高鲸郊,而水平滾動時為寬度起作用丰榴,如圖。
* @property (CGSize) headerReferenceSize
* @property (CGSize) footerReferenceSize
* -collectionView:layout:referenceSizeForHeaderInSection:
* -collectionView:layout:referenceSizeForFooterInSection:
* 縮進
* @property UIEdgeInsets sectionInset;
* -collectionView:layout:insetForSectionAtIndex:
總結
一個UICollectionView的實現(xiàn)包括兩個必要部分:UICollectionViewDataSource和UICollectionViewLayout秆撮,和一個交互部分:UICollectionViewDelegate四濒。而Apple給出的UICollectionViewFlowLayout已經是一個很強力的layout方案了。
幾個自定義的Layout
但是光是UICollectionViewFlowLayout的話职辨,顯然是不夠用的盗蟆,而且如果單單是這樣的話,就和現(xiàn)有的開源各類Grid View沒有區(qū)別了…UICollectionView的強大之處舒裤,就在于各種layout的自定義實現(xiàn)喳资,以及它們之間的切換。先看幾個相當exiciting的例子吧~
比如腾供,堆疊布局:
圓形布局:
和Cover Flow布局:
所有這些布局都采用了同樣的數(shù)據(jù)源和委托方法仆邓,因此完全實現(xiàn)了model和view的解耦。但是如果僅這樣伴鳖,那開源社區(qū)也已經有很多相應的解決方案了节值。Apple的強大和開源社區(qū)不能比擬的地方在于對SDK的全局掌控,CollectionView提供了非常簡單的API可以令開發(fā)者只需要一次簡單調用榜聂,就可以使用CoreAnimation在不同的layout之間進行動畫切換察署,這種切換必定將大幅增加用戶體驗,代價只是幾十行代碼就能完成的布局實現(xiàn)峻汉,以及簡單的一句API調用贴汪,不得不說現(xiàn)在所有的開源代碼與之相比脐往,都是相形見拙了…不得不佩服和感謝UIKit團隊的努力。
謝謝!!!