iOS UICollectionView詳解

//聯(lián)系人:石虎? QQ: 1224614774昵稱:嗡嘛呢叭咪哄

什么是UICollectionView

UICollectionView是一種新的數(shù)據(jù)展示方式,簡單來說可以把他理解成多列的UITableView(請一定注意這是UICollectionView的最最簡單的形式)。如果你用過iBooks的話,可能你還對書架布局有一定印象:一個虛擬書架上放著你下載和購買的各類圖書,整齊排列。其實這就是一個UICollectionView的表現(xiàn)形式,或者iPad的iOS6中的原生時鐘應用中的各個時鐘,也是UICollectionView的最簡單的一個布局,如圖:

最簡單的UICollectionView就是一個GridView,可以以多列的方式將數(shù)據(jù)進行展示。標準的UICollectionView包含三個部分,它們都是UIView的子類:

* Cells 用于展示內(nèi)容的主體,對于不同的cell可以指定不同尺寸和不同的內(nèi)容,這個稍后再說

* 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結(jié)果如何,都詢問是否可以被選中?

4. -collectionView:didUnhighlightItemAtIndexPath: 如果1回答為是,那么現(xiàn)在取消高亮

5. -collectionView:didSelectItemAtIndexPath: 如果3回答為是,那么選中cell

狀態(tài)控制要比以前靈活一些,對應的高亮和選中狀態(tài)分別由highlighted和selected兩個屬性表示。

關于Cell

相對于UITableViewCell來說,UICollectionViewCell沒有這么多花頭。首先UICollectionViewCell不存在各式各樣的默認的style,這主要是由于展示對象的性質(zhì)決定的,因為UICollectionView所用來展示的對象相比UITableView來說要來得靈活,大部分情況下更偏向于圖像而非文字,因此需求將會千奇百怪。因此SDK提供給我們的默認的UICollectionViewCell結(jié)構(gòu)上相對比較簡單,由下至上:

* 首先是cell本身作為容器view

* 然后是一個大小自動適應整個cell的backgroundView,用作cell平時的背景

* 再其上是selectedBackgroundView,是cell被選中時的背景

* 最后是一個contentView,自定義內(nèi)容應被加在這個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:

總結(jié)

一個UICollectionView的實現(xiàn)包括兩個必要部分:UICollectionViewDataSource和UICollectionViewLayout,和一個交互部分:UICollectionViewDelegate。而Apple給出的UICollectionViewFlowLayout已經(jīng)是一個很強力的layout方案了。

幾個自定義的Layout

但是光是UICollectionViewFlowLayout的話,顯然是不夠用的,而且如果單單是這樣的話,就和現(xiàn)有的開源各類Grid View沒有區(qū)別了…UICollectionView的強大之處,就在于各種layout的自定義實現(xiàn),以及它們之間的切換。先看幾個相當exiciting的例子吧~

比如,堆疊布局:

圓形布局:

和Cover Flow布局:

所有這些布局都采用了同樣的數(shù)據(jù)源和委托方法,因此完全實現(xiàn)了model和view的解耦。但是如果僅這樣,那開源社區(qū)也已經(jīng)有很多相應的解決方案了。Apple的強大和開源社區(qū)不能比擬的地方在于對SDK的全局掌控,CollectionView提供了非常簡單的API可以令開發(fā)者只需要一次簡單調(diào)用,就可以使用CoreAnimation在不同的layout之間進行動畫切換,這種切換必定將大幅增加用戶體驗,代價只是幾十行代碼就能完成的布局實現(xiàn),以及簡單的一句API調(diào)用,不得不說現(xiàn)在所有的開源代碼與之相比,都是相形見拙了…不得不佩服和感謝UIKit團隊的努力。

謝謝!!!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內(nèi)容

  • 文章鏈接 blog.csdn.net/sinat_34194127/article/details/5181897...
    whong736閱讀 5,708評論 0 2
  • 什么是UICollectionView? UICollectionView是一種新的數(shù)據(jù)展示方式,簡單來說可以把他...
    凌峰Mical閱讀 43,383評論 11 201
  • 我是女生,看到有的男生想追自己喜歡的女孩子又不敢追,還想人家倒追她,我很反感. 從一個女生的角度,我比較了解女孩子...
    胡彬?qū)憣?/span>閱讀 361評論 0 0
  • 月光寶盒,菠蘿菠蘿 我踏過千山萬水,日月如梭 物是人非黃花瘦 恍惚五百年前的盡頭 是俺老孫鬧天宮時的英雄 可現(xiàn)在凡...
    贈遠閱讀 213評論 0 6
  • 這次唐山之行學習,實際上是醫(yī)院臨床跟師,在宮老師強大理論的支撐下,通過老師手把手的教課,自己的實際病號操作,技術會...
    1040ad7b6a89閱讀 186評論 0 2