目录
* UICollectionView
的定义
* UICollectionView
快速构建GridView网格视图
* UICollectionView
拖拽重排处理(iOS8.x-/iOS9.x+)
* UICollectionView
实现简单轮播
UICollectionView的定义
UICollectionView
同UITableView
一样,是iOS中最常用到数据展示视图。
官方定义:
An object that manages an ordered collection of data items and presents them using customizable layouts.
提供管理有序数据集合且可定制布局能力的对象
UICollectionView
显示内容时:
- 通过
dataSource
获取cell
- 通过
UICollectionViewLayout
获取layout attributes
布局属性 - 通过对应的
layout attributes
对cell
进行调整,完成布局
- 通过
UICollectionView
交互则是通过丰富的delegate
方法实现
iOS10中增加了一个新的预处理protocol UICollectionViewDataSourcePrefetching 帮助预加载数据 缓解大量数据加载带来的快速滑动时的卡顿
UICollectionView视图
一个标准的UICollectionView
视图包括以下三个部分
UICollectionViewCell
视图展示单元SupplementaryView
追加视图,类似我们熟悉的UITableView
中的HeaderView
、FooterVIew
DecorationView
装饰视图
1.UICollectionView
依然采用Cell
重用的方式减小内存开支,所以需要我们注册并标记,同样,注册分为Class
及nib
两类
// register cell
if (_cellClassName) {
[_collectionView registerClass:NSClassFromString(_cellClassName) forCellWithReuseIdentifier:ReuseIdentifier];
}
if (_xibName) {
// xib
[_collectionView registerNib:[UINib nibWithNibName:_xibName bundle:nil] forCellWithReuseIdentifier:ReuseIdentifier];
}
2.Father Apple同样将重用机制带给了SupplementaryView
,注册方法同Cell
类似
// UIKIT_EXTERN NSString *const UICollectionElementKindSectionHeader NS_AVAILABLE_IOS(6_0);
// UIKIT_EXTERN NSString *const UICollectionElementKindSectionFooter NS_AVAILABLE_IOS(6_0);
- (void)registerClass:(nullable Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
- (void)registerNib:(nullable UINib *)nib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)identifier;
对于它尺寸的配置,同样交由Layout
处理,如果使用的是UICollectionViewFlowLayout
,可以直接通过headerReferenceSize
或footerReferenceSize
赋值
3.DecorationView
装饰视图,是我们在自定义Custom Layout
时使用
UICollectionViewDataSource及UICollectionViewDelegate
这个部分使用频率极高想必大家都非常熟悉,所以笔者列出方法,不再赘述。
UICollectionViewDataSource(* 需要着重关注下iOS9后出现的两个新数据源方法,在下文中介绍拖拽重排时会用到他们 *)
@required
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
// The view that is returned must be retrieved from a call to -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath NS_AVAILABLE_IOS(9_0);
UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(8_0);
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
官方注释解释了交互后调用的顺序
// (when the touch begins)
// 1. -collectionView:shouldHighlightItemAtIndexPath:
// 2. -collectionView:didHighlightItemAtIndexPath:
//
// (when the touch lifts)
// 3. -collectionView:shouldSelectItemAtIndexPath: or -collectionView:shouldDeselectItemAtIndexPath:
// 4. -collectionView:didSelectItemAtIndexPath: or -collectionView:didDeselectItemAtIndexPath:
// 5. -collectionView:didUnhighlightItemAtIndexPath:
使用代理
的方式处理数据及交互,好处是显而易见的,代码功能分工非常明确,但是也造成了一定程度上的代码书写的繁琐。所以本文会在快速构建部分,介绍如何使用Block
实现链式传参书写
UICollectionViewLayout布局
不同于UITableView
的简单布局样式,UICollectionView
提供了更加强大的布局能力,将布局样式任务分离成单独一个类管理,就是我们初始化时必不可少UICollectionViewLayout
Custom Layout
通过UICollectionViewLayoutAttributes
,配置不同位置Cell的诸多属性
@property (nonatomic) CGRect frame;
@property (nonatomic) CGPoint center;
@property (nonatomic) CGSize size;
@property (nonatomic) CATransform3D transform3D;
@property (nonatomic) CGRect bounds NS_AVAILABLE_IOS(7_0);
@property (nonatomic) CGAffineTransform transform NS_AVAILABLE_IOS(7_0);
@property (nonatomic) CGFloat alpha;
@property (nonatomic) NSInteger zIndex; // default is 0
同样也可以通过Layout提供诸多行为接口
动态修改Cell的布局属性
贴心的Father Apple为了让我们