您的位置:首页 > 产品设计 > UI/UE

UICollectionView(一)基本概念

2015-11-03 15:49 405 查看
整体预览

高等级的包含和管理(Top-level containment and management)

UICollectionView

UICollectionViewController

UICollectionView对象为collection view的内容定义了显示的区域。该类是 UIScrollView的子类,能够拥有大量的滚动区域,同时该类能够更具布局对象的布局信息,非常方便的显示数据。

UICollectionViewController对象提供视图控制器等级的管理支持,根据需求可以选择是否使用。

内容管理(Content management)

UICollectionViewDataSource

UICollectionViewDelegate

数据源对象( data source object)是与collection view相关联的最重要对象,并且我们必须提供。该对象管理着collection view的内容并且创建视图显示内容。为了实现数据源对象,我们必须创建一个对象遵守UICollectionViewDataSource协议。

UICollectionView的代理对象能够让我们拦截来自collection view有趣的信息并且自定义view的行为。例如:我们使用代理对象来跟踪在collection view中选中和高亮的item对象,不像数据源对象,代理对象是可选的。对于跟多的信息,可以看Designing Your Data Source and Delegate.

显示内容(Presentation)

UICollectionReusableView

UICollectionViewCell

所有显示在UICollectionView中的views都必须是UICollectionReusableView类的实例。通过使用UICollectionView该类支持循环机制。重复利用视图将提高整体的性能,特别是滚动的流畅。

UICollectionViewCell 对象是具体类型的重用视图,用于展示我们的数据。

布局(Layout)

UICollectionViewLayout

UICollectionViewLayoutAttributes

UICollectionViewUpdateItem

UICollectionViewLayout和子类作为布局对象主要负责定义位置、大小、cell的可视属性,以及collection view中重用的视图。

在布局过程中,一个布局对象(layout objects)将创建布局属性对象(layout attribute objects),该属性对象是UICollectionViewLayoutAttributes类的实例,它将告诉collection view在哪里以及怎样显示cells和重用视图。

无论什么时候数据item在collection view中进行插入 (inserted)、删除(deleted)、移动(move),布局对象接受UICollectionViewUpdateItem类的实例,我们从未使用该类自己创建实例。对于更多有关布局对象信息,可以看 The Layout Object Controls the Visual Presentation.

流动布局(Flow layout)

UICollectionViewFlowLayout

UICollectionViewDelegateFlowLayout

UICollectionViewFlowLayout类是具体的布局对象,能够用于实现网格或者其它基于线性的布局。我们能够直接使用该类,或者设置flow代理,UICollectionViewDelegateFlowLayout协议中提供了大量的方法来方便我们自定义布局信息。

下图显示了核心对象与collection view之间的关系。collection view从数据源(data source )获取cells显示的相关信息。数据源(data source)和代理(delegate)对象需要APP提供自定义对象并用于管理内容,包括选中和高亮的cells。布局对象(layout object)主要负责确定cell的位置,并且通过提供一个或者多个布局属性对象发送相关信息给collection view,collection view将布局信息与cell合并创建最终的可视界面。

Figure 1-1 Merging content and layout to create the final presentation



什么是UICollectionView?

UICollectionView是一种新的数据展示方式,简单来说可以把他理解成多列的UITableView.

标准的UICollectionView包含三个部分,它们都是UIView的子类:

Cells 用于展示内容的主体,对于不同的cell可以指定不同尺寸和不同的内容.

Supplementary Views 追加视图可以理解为每个Section的Header或者Footer,用来标记每个section的view.

Decoration Views 装饰视图 这是每个section的背景.

与UITableView的对比:

UITableView是iOS开发中的非常重要的一个类,对这个类应该是非常熟悉了。实现一个UICollectionView和实现一个UITableView基本没有什么大区别,它们都同样是datasource和delegate设计模式的:datasource为view提供数据源,告诉view要显示些什么东西以及如何显示它们,delegate提供一些样式的小细节以及用户交互的相应。

UICollectionViewDataSource中:

section的数量 -numberOfSectionsInCollection:

某个section里有多少个item -collectionView:numberOfItemsInSection:

对于某个位置应该显示什么样的cell -collectionView:cellForItemAtIndexPath:

实现以上三个委托方法,基本上就可以保证CollectionView工作正常了。

当然,还有提供Supplementary View的方法.collectionView:viewForSupplementaryElementOfKind:atIndexPath:

对于Decoration Views,提供方法并不在UICollectionViewDataSource中,而是直接UICollectionViewLayout类中的(因为它仅仅是视图相关,而与数据无关).

关于重用问题

为了得到高效的View,对于cell的重用是必须的,避免了不断生成和销毁对象的操作,这与在UITableView中的情况是一致的。但值得注意的时,在UICollectionView中,不仅cell可以重用,Supplementary View和Decoration View也是可以并且应当被重用的。在iOS5中,Apple对UITableView的重用做了简化,以往要写类似这样的代码:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {    //如果没有可重用的cell,那么生成一个
cell = [[UITableViewCell alloc] init];
}
return cell


而如果我们在TableView向数据源请求数据之前使用-registerNib:forCellReuseIdentifier:方法为@“cell”注册过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配置了:

- (UICollectionView*)collectionView:(UICollectionView*)cv cellForItemAtIndexPath:(NSIndexPath*)indexPath {
MyCell *cell = [cv dequeueReusableCellWithReuseIdentifier:@cell”];
// Configure the cell's content
cell.imageView.image = ...
return cell;
}


UICollectionViewDelegate

数据无关的view的外形啊,用户交互的,由UICollectionViewDelegate来负责:

cell的高亮

cell的选中状态

可以支持长按后的菜单

关于用户交互,UICollectionView也做了改进。每个cell现在有独立的高亮事件和选中事件的delegate,用户点击cell的时候,现在会按照以下流程向delegate进行询问:

-collectionView:shouldHighlightItemAtIndexPath: 是否应该高亮?

-collectionView:didHighlightItemAtIndexPath: 如果1回答为是,那么高亮

-collectionView:shouldSelectItemAtIndexPath: 无论1结果如何,都询问是否可以被选中?

-collectionView:didUnhighlightItemAtIndexPath: 如果1回答为是,那么现在取消高亮

-collectionView:didSelectItemAtIndexPath: 如果3回答为是,那么选中cell

状态控制要比以前灵活一些,对应的高亮和选中状态分别由highlighted和selected两个属性表示。

使用UICollectionViewFlowLayout定制对象布局:

创建UICollectionViewFlowLayout布局对象.如果直接使用UICollectionViewFlowLayout布局对象来管理UICollectionView的所有单元格,那么这些单元格德大小,间距和行距都是相同的.那么可以实现非常整齐的网格效果.

但是在某些时候,UICollectionView控件中各个单元格的大小参差不齐,如果强行就爱那个这些控件缩放到统一大小,势必会影响效果.如果程序需要让UICollectionView中各控件各自显示不同的大小,则可借助于UICollectionViewDelegateFlowLayout协议来实现.该UICollectionViewDelegateFlowLayout协议继承于UICollectionViewDelegate,因此实现该协议对象可以当做UICollectionView的委托对象使用.UICollectionViewDelegateFlowLayout协议定义了如下方法:

(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;该方法返回的CGSize对象将指定控制NSIndexPath对应单元格的大小.

(UIEdgeInsets)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;

该方法返回UIEdgeInsets对象控制指定分区上下左右空白大小.

(CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;

该方法返回的长度值将控制指定分区内最小的行间距.

(CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;

该方法返回的长度值将控制指定分区内最小的列间距.

(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;

该方法返回的CGSize将控制指定分区头的大小

(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;

该方法返回的CGSize将控制指定分区尾部的大小单使用一下:

下面一起来简单的使用一下:

#import "ViewController.h"

@interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>{
NSArray *_books;
NSArray *_coversImage;
}
@property (weak, nonatomic) IBOutlet UICollectionView *grid;
@end
@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

_books=@[@"好好学习",@"好好学习",@"好好学习",@"好好学习",
@"好好学习",@"好好学习",@"好好学习",@"好好学习",
@"好好学习",@"好好学习",@"好好学习",@"好好学习",
@"好好学习",@"好好学习",@"好好学习",@"好好学习",
@"好好学习",@"好好学习",@"好好学习",@"好好学习",
@"好好学习",@"好好学习",@"好好学习",@"好好学习"];

_coversImage=@[@"jt_03.png",@"jt_03.png",@"jt_03.png",@"jt_03.png",
@"jt_03.png",@"jt_03.png",@"jt_03.png",@"jt_03.png",
@"jt_03.png",@"jt_03.png",@"jt_03.png",@"jt_03.png",
@"jt_03.png",@"jt_03.png",@"jt_03.png",@"jt_03.png",
@"jt_03.png",@"jt_03.png",@"jt_03.png",@"jt_03.png",
@"jt_03.png",@"jt_03.png",@"jt_03.png",@"jt_03.png"];

self.navigationItem.title = @"学习目标";

UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];

// 设置UICollectionView中各单元格的大小.
//flowLayout.itemSize = CGSizeMake(150,150);
// 设置该UICollectionView只支持水平滚动.用于设置方向
//flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
// 设置各分区上、下、左、右空白的大小。
flowLayout.sectionInset = UIEdgeInsetsMake(0, 2, 0, 0);
self.grid.delegate = self;
self.grid.dataSource = self;

// 为UICollectionView设置布局对象
self.grid.collectionViewLayout = flowLayout;

}

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

return _books.count;
}

//也可以实现UICollectionViewDelegateFlowLayout代理,设置 item 大小.
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{

return  CGSizeMake(150,150);
}

// 该方法返回值决定各单元格的控件。
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

// 为单元格定义一个静态字符串作为标示符,在使用之前一定要提前注册cell,否则会崩溃.这里是因为在storyboard中已经注册.
static NSString * cellID = @"cell";

// 从可重用单元格的队列中取出一个单元格
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

// 设置圆角
cell.layer.cornerRadius = 8;
cell.layer.masksToBounds = YES;

// 为单元格内图片控件设置图片
UIImageView *image = (UIImageView *)[cell viewWithTag:1000];
image.image = [UIImage imageNamed:_coversImage[indexPath.row]];

// 为单元格内UILabel控件设置文本
UILabel *label = (UILabel *)[cell viewWithTag:1001];
label.text = _books[indexPath.row];

cell.backgroundColor = [UIColor redColor];
return cell;
}


实现效果如下:简单的网格布局界面

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: