UICollectionView的布局是可以自己定义的,在这篇博客中先在上篇博客的基础上进行扩充,我们先使用UICollectionViewFlowLayout,然后好好的介绍一下UICollectionView的一些回调方法,主要包括UICollectionViewDataSource,UICollectionViewDelegateFlowLayout,UICollectionViewDelegate相关回调方法,并通过实例来介绍每个回调的用法。并且给每个Section添加定制的Header和Footer,好废话少说进入今天的正题。
一、Demo总览
下图是本篇博客中Demo的最终运行效果,下面是我们要做的事情:
1. 给每个Section添加自定义的重用Header和Footer
2.调整第一个Section的上左下右的边距(UIEdgeInsets)
3.给UICollectioinView设置多选
4.处理Cell的高亮事件
5.处理Cell的选中事件
6.调整Cell的上下左右边距
7.对Cell进行编辑
二、UICollectionViewDataSource介绍
1、在UICollectionViewDataSource回调方法中有一个返回Section数量的方法,如下所示,该方法和UITableView中的用法一致。在这儿我们返回5个Section,如下所示:
1 2 3 4 5 6 7 8 |
#pragma mark /** * 返回Section的个数 */ - (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView { return 5; } |
2、在UICollectionViewDataSource的回调方法中,还有一个是返回每个Section中Cell的数量的方法,在这我们返回30个Cell, 如下代码所示:
1 2 3 4 5 6 7 8 |
/** * 返回每个Section中Cell的个数 */ - (NSInteger)collectionView: (UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section { return 30; } |
3、在UICollectionViewDataSource还有一个必须实现的方法, 就是选择我们CollectionView中所使用的Cell, 在这里我们所使用的Cell是在Storyboard上实现的,所以不需要在我们的代码中注册Cell, 之间使用重用标示符就可以获取Cell的对象,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * 返回Cell种类 */ - (UICollectionViewCell *)collectionView: (UICollectionView *)collectionView cellForItemAtIndexPath: (NSIndexPath *)indexPath { //通过Cell重用标示符来获取Cell CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier: reuseIdentifier forIndexPath: indexPath]; return cell; } |
4、在UICollectionViewDataSource方法中有一个可选的方法就是为我们的Section添加Supplementary View(追加视图),下面是添Supplementary View(追加视图)的步骤。在UICollectionView中的Section中我们可以为其增加Header View和Footer View, 也就是官方文档上提到的Supplementary View(追加视图)。追加视图是可以重用的,也就是UICollectionReusableView。我们可以创建两个UICollectionReusableView的子类,一个是Header View, 另一个是Footer View。
(1)创建UICollectionReusableView
追加视图可以在Storyboard上添加,然后设置重用标示符,在代码中使用即可。这里我们是从xib文件来加载的Supplementary View, 先创建两个UICollectionReusableView子类,在创建该子类的同时创建相应的xib文件,如下所示:
创建Header View和Footer View的UICollectionReusableView,创建后的文件目录如下:
(2) 因为我们是从xib文件中加载的UICollectionReusableView,所以需要在相应的UICollectionView上进行注册。如果你是使用的Storyboard, 只需要在Storyboard中指定重用标示符即可。下面的代码就是在ViewDidLoad中调用注册UICollectionReusableView的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/** * 注册Header和FooterView * 便于在UICollectionViewDataSource中使用 */ - (void) registerHeaderAndFooterView { //注册headerView //获取含有UICollectionReusableView的Nib文件。 UINib *headerNib = [UINib nibWithNibName: @"CollectionHeaderReusableView" bundle: [NSBundle mainBundle]]; //注册重用View [self.collectionView registerNib: headerNib forSupplementaryViewOfKind: UICollectionElementKindSectionHeader withReuseIdentifier: @"CollectionHeaderReusableView"]; //注册FooterView UINib *footerNib = [UINib nibWithNibName: @"CollectionFooterReusableView" bundle:[ NSBundle mainBundle]]; [self.collectionView registerNib: footerNib forSupplementaryViewOfKind: UICollectionElementKindSectionFooter withReuseIdentifier: @"CollectionFooterReusableView"]; } |
(3)在UICollectionViewDataSource中的设置Supplementary View的方法中通过Header View和Footer View的重用标示符来为我们的Section设置Supplementary View,具体代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/** * 设置Setion的Header和Footer(Supplementary View) */ - (UICollectionReusableView *)collectionView: (UICollectionView *)collectionView viewForSupplementaryElementOfKind: (NSString *)kind atIndexPath: (NSIndexPath *)indexPath{ //设置SectionHeader if ([kind isEqualToString: UICollectionElementKindSectionHeader]) { UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CollectionHeaderReusableView" forIndexPath:indexPath]; return view; } //设置SectionFooter UICollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"CollectionFooterReusableView" forIndexPath:indexPath]; return view; } |
UICollectionViewDataSource中的四个方法在上面都进行了实现,UICollectionViewDataSource主要是负责加载数据源的,包括Section的个数,每个Section中Cell的个数,每个Section中Supplementary View的种类。
三.UICollectionViewDelegateFlowLayout回调实现
UICollectionViewDelegateFlowLayout主要是负责显示的,比如Secion的大小、边距,Cell的大小边距,headerView的大小已经FooterView的大小,都是在UICollectionViewDelegateFlowLayout的相应协议的方法来实现的。接下来详细的介绍一下UICollectionViewDelegateFlowLayout协议中的方法。
1.同一个Section中同一种Cell(通过同一个Cell重用标示符获取的对象)可以有不同的尺寸,下面的代码是给Cell定制尺寸。代码的具体意思是第一个Section中的所有Cell的尺寸是(50,50)。 其余的时(60,60)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#pragma mark /** * 改变Cell的尺寸 */ - (CGSize)collectionView: (UICollectionView *)collectionView layout: (UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath: (NSIndexPath *)indexPath{ if (indexPath.section == 0) { return CGSizeMake(50, 50); } return CGSizeMake(60, 60); } |
2.改变Section的上下左右边距–UIEdgeInsetsMake(上, 左, 下, 右),逆时针旋转。第一个Section的上左下右的边距都是50, 其余的Section上左下右的边距是0。具体实现看如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * Section的上下左右边距--UIEdgeInsetsMake(上, 左, 下, 右);逆时针 */ - (UIEdgeInsets)collectionView: (UICollectionView *)collectionView layout: (UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex: (NSInteger)section{ if (section == 0) { return UIEdgeInsetsMake(50, 50, 50, 50); } return UIEdgeInsetsMake(0, 0, 0, 0); } |
3.设置每个Cell的上下边距的回调如下所示,第一个Section的Cell上下边距是5.0f, 其余的为20.0f。
1 2 3 4 5 6 7 8 9 10 11 |
/** * Section中每个Cell的上下边距 */ - (CGFloat)collectionView: (UICollectionView *)collectionView layout: (UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex: (NSInteger)section{ if (section == 0) { return 5.0f; } return 20.0f; } |
4.设置Cell的左右边距,第一个Section的Cell左右边距是5.0f, 其余的为20.0f。