在前面咱们已经学过,每一个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标识符。
如今运行代码,咱们能够看到运行的结果: