在前面咱們已經學過,每一個collection view都必須有數據源爲其提供內容。它的責任是爲collection views完成如下的事情:數組
控制collection view的section數目app
每一個section中的item的個數ide
爲特定的數據項提供cell view佈局
顯然,簡單的Recipe app,咱們在前面的教程中包含了其中一個部分,在這裏咱們將繼續講講collection view而且告訴你如何利用不一樣的section組織items,你將會學到怎樣爲collection view添加header視圖和footer視圖。
字體
若是你沒有看過前面的教程,建議你去看一看前面的教程,或者你能夠到這裏下載here。spa
Split Recipes into Two Sections in UICollectionView設計
在這個簡單的程序中,RecipeCollectionViewController是集合視圖的數據源對象,爲了把視圖分紅兩個部分,咱們須要有一些變化,接下來咱們完成:code
起先,recipeImages數組是存儲全部recipes的名稱,由於咱們想把recipes分紅兩組,咱們要修改咱們的代碼,並使用簽到數組來存儲不一樣的recipe,也許你還不明白啥是嵌入的數組,下面的圖片會讓你明白的。第一組包含主要的圖像,而另外一個爲drink和dessert。頂級數組(即recipeImages)包含兩個數組,每一個數組部分的特定區域包含特定的data items。orm
讓咱們開始編寫代碼,在RecipeCollectionViewController.m中初始化"recipeImages"數組,並在viewDidload方法中寫下面的方法:對象
- (void)viewDidLoad
{
[super viewDidLoad];
//Initialize recipe image array
NSArray *mainDishImages = [NSArray arrryWithObjects:@"egg_benedict.jpg", @"full_breakfast.jpg", @"ham_and_cheese_panini.jpg", @"ham_and_egg_sandwich.jpg", @"hamburger.jpg", @"instant_noodle_with_egg.jpg", @"japanese_noodle_with_pork.jpg", @"mushroom_risotto.jpg", @"noodle_with_bbq_pork.jpg", @"thai_shrimp_cake.jpg", @"vegetable_curry.jpg", nil];
NSArray *drinkDessertImages = [NSArray arrayWithObjects:@"angry_birds_cake.jpg", @"creme_brelee.jpg", @"green_tea.jpg", @"starbucks_coffee.jpg", @"white_chocolate_donut.jpg", nil];
recipeImages = [NSArray arrayWithObjects:mainDishImages,drinkDesserImages,nil];
}
上面的代碼將recipes images分紅兩組。接下來,修改"numberOfIntemsInSecion:"方法來返回,每一個secions中的items數目:
- (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSecion:(NSInteger)section
{
return [[recipeImages objectAtIndex:sectin]count];
}
接下來咱們按照下面的方法修改"cellForItemAtIndexPath:"方法
- (UICollectionVIewCell *)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"Cell";
RecipeViewCell *cell = (RecipeViewCell *)[collectionView dequeueReuseIdentifier:identifier forIndexPath:indexPath];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imagedNamed:[recipeImages[indexPath.section] objectAtIndex:indexPath.row]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"photo-frame-2.png"]];
return cell;
}
你能夠和之前的代碼比較如下,你就會知道只有同樣是惟一的變化。咱們首先檢索該數組的section number而後從section中獲取具體的items。
最後,怎樣給collection view實現兩個section,這個能夠經過方法調用下面的方法來完成即:在RecipeCollectionViewController.m中的numberOfSectionsInCollectionView方法,在collectin View中返回section中的數量。
- (NSInteger)numberOfSectionsInCollectionVIew:(UICollectionView *)collectionView
{
return [recipeImages count];
}
如今運行你的app,你會在屏幕上看到下面的顯示
(利用Section Insets)
程序是完成了,可是你是否以爲看起來並不怎麼順眼呢?圖像的第一部分的最後一行和第二部分的第同樣靠的太近。咱們可使用插入圖到內容周圍的空間中來改變一些格局,經過下圖你能夠比較直觀 的看到影響:
你能夠利用UIEdgeInsetsMake來完成插入:
insert = UIEdgeInsetsMake(top,left,botton,right);
在咱們的Recipe app中咱們只能在兩個section之間添加空間。在RecipeCollectionViewController.m文件中的ViewDidLoad方法中,添加下面的方法:
UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout *)self.collectionViewFlowLayout;
collectionViewLayout.sectionInset = UIEdegeInsetsMake(20,0,0,0);
上面的代碼實現了在collection view中建立和添加插入。如今咱們運行程序,你將會看到下面的 圖像顯示,咱們在兩個section之間增長了一些空間。
添加頭部和底部視圖
如今咱們進一步調整應用程序,讓其更酷。讓咱們來給應用程序添加頭部和底部視圖,咱們利用UICollectionViewFlowLayout來實現這一點。這裏的header和footer視圖能夠被稱爲流佈局的補充。在默認狀況下,這些視圖是在流佈局中禁用的。但能夠經過下面幾件事情來配置header和footer視圖:
爲了儘可能保持簡單,因此咱們能夠選擇storyboard來實現(固然這不是必須的,你一樣可使用代碼來實現這一點)
實現 UICollectionViewDataSource協議的 collectionView:viewForSupplementaryElementOfKind 方法,並經過這個方法來實現補充試圖在collection view中顯示。
在Storyboard中設計Header和Footer
首先download the header/footer background images而且添加到Xcode工程中。
到Storyboard中,選擇collection view controller中的"Collection View"。在Attributes inspector中,選擇"Section Header"和"Section Footer",一旦選中你就會在屏幕中看到下面的的顯示:
在header和footer之間默認爲空,咱們會用storyboard來設計視圖。header view是專門用來顯示一個部分的標題,而底部視圖只顯示靜態橫幅圖片。利用storyboard,從對象庫中拖出image view並在其上面添加一個標籤。設置字體顏色爲白色,底部視圖只需添加一個image view。如圖:
選中footer view中的image view,在Attributes inspector中命名背景圖片爲"footer_banner.png"
最重要的是,咱們必須爲header和footer view指定一個標識符。這個標示符將會被用於代碼識別圖片名稱。在Atteributes inspector中設置header view的identifier爲「HeaderView」,一樣的把footer view的identifier設置爲「FooterView」。
爲Header View添加新類
在默認狀況下,header和footer view和UICollectionResuable類相關聯。爲了在header view中顯示咱們須要的背景和標題,咱們必須建立一個新的繼承自UICollectionResuableView的類,咱們能夠命名爲RecipeCollectionHeaderView。
在storyboard的Identifier inspector中的sustom class設置爲「RecipeCollectionHeaderView」。按住Ctrl鍵,單機header中的image view,並拖向RecipeCollectionHeaderView.h中插入一個Outlet 變量。命名變量爲"backgroundImage"。重複一樣的步驟對UILabel實現,而後命名爲"title"。
實現viewForSupplementaryElementOfKind方法
若是你嘗試運行應用程序,你可能不會看到header和footer,這是由於咱們尚未實現"viewFOrSupplementaryElementOfKind:"方法。選擇「RecipeCollectionViewController」,並添加import語句。
#import "RecipeCollectionHeaderView.h"
下面就是實現viewforSupplementaryElementOfKind方法的代碼:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableview = nil;
if (kind == UICollectionElementKindSectionHeader){
RecipeCollectionHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];
NSString *title = [[NSString alloc] initWithFormat:@"Recipe Group #%i",indexPath.section +1];
headerView.title.text = title;
UIImage *headerImage = [UIImage imageNamed:@"header_banner.png"];
headerView.backgroundImage.image = headerImage;
reusableView = headerView;
}
if (kind == UICollectionElementKindSectionFooter){
UICollectionReusableView *footerview = [collectionView dequeueResuableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FooterView" forIndexPath:indexPath];
reusableview = footerview;
}
return reusableview;
}
上面的代碼告訴它頁眉/頁腳視圖應該在每一個部分中使用collect view。咱們首先肯定該集合視圖要求header或footer view。這能夠經過使用一種變量來完成。對於頭來看,咱們出列header view(使用dequeueReusableSupplementaryViewOfKind :方法),並設置適當的標題和圖像。正如你能夠從兩個if之間的代碼,咱們使用咱們以前分配給得到header/footer view標識符。
如今運行代碼,咱們能夠看到運行的結果: