UICollectionView(集合视图学习笔记)
集合视图的作用
管理数据项的有序集合并使用可自定义布局显示它们的对象。集合视图是为了增强网格视图开发而在IOS6中开放的集合视图API。
集合视图的组成
集合视图有4个重要的组成部分,分别为:
- 单元格:即视图中的一个单元格。
- 节:即集合视图中的一个行数据,由多个单元格构成。
- 补充视图:即节的头和脚。
- 装饰视图:集合视图中的背景视图。
集合视图
集合视图UICollectionView继承自UIScrollView。集合视图也有两个协议:UICollectionViewDelegate委托协议和UICollectionViewDataSource数据源协议。UICollectionViewCell是单元格类,它的布局是由UICollectionViewLayout类定义的,它是一个抽象类。UICollectionViewFlowLayout类是UICollectionViewLayout类的子类,对于复杂的布局,可以自定义UICollectionViewLayout类。UICollectionView对应的控制器是UICollectionViewController类。
将集合视图添加到用户界面时,应用程序的主要任务是管理与该集合视图关联的数据。集合视图从数据源对象获取其数据,该对象符合UICollectionViewDataSource协议,由应用程序提供。集合视图中的数据被组织到各个项目中,然后可以将这些项目分组到各个部分中进行表示。项是要显示的最小数据单位。例如,在照片应用程序中,项目可能是单个图像。集合视图使用单元格在屏幕上显示项,单元格是数据源配置和提供的UICollectionViewCell类的实例。
除了单元格之外,集合视图还可以使用其他类型的视图显示数据。这些补充视图可以是独立于单个单元格的节页眉和页脚,但仍然传递某种类型的信息。对补充视图的支持是可选的,由集合视图的布局对象定义,该对象还负责定义这些视图的位置。
除了将其嵌入到用户界面之外,还可以使用UICollectionView对象的方法来确保项的可视表示与数据源对象中的顺序相匹配。因此,无论何时在集合中添加、删除或重新排列数据,都要使用该类的方法来插入、删除和重新排列相应的单元格。您还可以使用集合视图对象来管理所选的项,不过对于这种行为,集合视图使用其关联的委托对象。
单元格
集合视图单元格是集合视图中最为重要的组成部分,没有样式和风格定义,单元格就是一个视图,可以在内部放置其他视图或控件。自定义一个单元格类,它需要继承UICollectionViewCell。
UICollectionView的一些常用属性
@property (nonatomic, strong) UICollectionViewLayout *collectionViewLayout;
属性描述 : 用于组织集合视图项的布局。将新布局对象指定给此属性会导致将新布局(不带动画)应用于集合视图的项。
@property (nonatomic, strong) UICollectionViewLayout *collectionViewLayout;
@property (nonatomic, weak, nullable) id <UICollectionViewDelegate> delegate;
属性描述 : 充当集合视图的委托的对象。委托必须采用UICollectionViewDelegate协议。集合视图维护对委托对象的弱引用。委托对象负责管理选择行为和与单个项的交互。
@property (nonatomic, weak, nullable) id <UICollectionViewDelegate> delegate;
@property (nonatomic, weak, nullable) id <UICollectionViewDataSource> dataSource;
属性描述 :为集合视图提供数据的对象。数据源必须采用UICollectionViewDataSource协议。集合视图维护对数据源对象的弱引用。
@property (nonatomic, weak, nullable) id <UICollectionViewDataSource> dataSource;
@property (nonatomic, strong, nullable) UIView *backgroundView;
属性描述 : 提供背景外观的视图。此属性中的视图(如果有)位于所有其他内容的下面,并自动调整大小以填充集合视图的整个边界。背景视图不与集合视图的其他内容一起滚动。集合视图维护对背景视图对象的强引用。默认情况下,此属性为nil,它显示集合视图的背景色。
@property (nonatomic, strong, nullable) UIView *backgroundView;
@property (nonatomic) BOOL allowsSelection;
属性描述 : 指示用户是否可以在集合视图中选择项的布尔值。如果此属性的值为YES(默认值),则用户可以选择项。如果希望对项的选择进行更细粒度的控制,则必须提供委托对象并实现UICollectionViewDelegate协议的适当方法。
@property (nonatomic) BOOL allowsSelection;
@property (nonatomic) BOOL allowsMultipleSelection;
属性描述 : 一个布尔值,用于确定用户是否可以在集合视图中选择多个项。此属性控制是否可以同时选择多个项。此属性的默认值为NO。当此属性的值为YES时,单击单元格将其添加到当前选择中(假设委托允许选择该单元格)。再次点击单元格将其从选择中移除。
@property (nonatomic) BOOL allowsMultipleSelection;
@property (nonatomic, readonly) NSInteger numberOfSections;
函数描述 : 返回集合视图显示的节数。
@property (nonatomic, readonly) NSInteger numberOfSections;
@property (nonatomic, readonly) NSArray<__kindof UICollectionViewCell *> *visibleCells;
属性描述 : 返回集合视图当前显示的可见单元格数组。UICollectionViewCell对象的数组。如果没有可见的单元格,则返回空数组。
@property (nonatomic, readonly) NSArray<__kindof UICollectionViewCell *> *visibleCells;
@property (nonatomic, readonly) NSArray<NSIndexPath *> *indexPathsForVisibleItems;
属性描述 : 集合视图中可见项的数组。此属性的值是NSIndexPath对象的未排序数组,每个对象都对应于集合视图中的可见单元格。此数组不包含任何当前可见的补充视图。如果没有可见项,则此属性的值为空数组。
@property (nonatomic, readonly) NSArray<NSIndexPath *> *indexPathsForVisibleItems;
UICollectionView的一些常用函数
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_DESIGNATED_INITIALIZER;
函数描述 : 使用指定的框架(frame)和布局(layout)初始化并返回新分配的集合视图对象。以编程方式初始化集合视图对象时使用此方法。此方法是指定的初始值设定项。
参数 :
frame : 集合视图的边框矩形,以点为单位。框架的原点相对于要在其中添加它的超视图。此frame在初始化期间传递给超类。
layout : 用于组织项的布局对象。集合视图存储对指定对象的强引用。不能为nil。
返回值 : 初始化的集合视图对象,如果无法创建该对象,则为nil。
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout NS_DESIGNATED_INITIALIZER;
例如 :
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:layout];
- (void)registerClass:(nullable Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
函数描述 : 注册一个类以用于创建新的集合视图单元格。在调用集合视图的dequeueReusableCellWithReuseIdentifier:forIndexPath:方法之前,必须使用此方法或registerNib:forCellWithReuseIdentifier:方法告诉集合视图如何创建给定类型的新单元格。如果指定类型的单元格当前不在重用队列中,则集合视图将使用提供的信息自动创建新的单元格对象。
如果以前用相同的重用标识符注册了类或nib文件,则在cellClass参数中指定的类将替换旧条目。如果要从指定的重用标识符中注销该类,可以为cellClass指定nil。
参数 :
cellClass : 要在集合视图中使用的单元格的类。
identifier : 要与指定类关联的重用标识符。此参数不能为nil,也不能为空字符串。
- (void)registerClass:(nullable Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
例如 :
[self.collectionView registerClass:[GoodsSalesDiscountItem class] forCellWithReuseIdentifier:@"item"];
- (void)registerClass:(nullable Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
函数描述 : 注册一个类,用于为集合视图创建补充视图。在调用集合视图的dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:方法之前,必须使用此方法或registerNib:forSupplementaryViewOfKind:withReuseIdentifier:method来告诉集合视图如何创建给定类型的补充视图。如果指定类型的视图当前不在重用队列中,则集合视图将使用提供的信息自动创建视图对象。
如果以前用相同的元素类型和重用标识符注册了类或nib文件,则在viewClass参数中指定的类将替换旧条目。如果要从指定的元素类型和重用标识符中注销该类,可以为viewClass指定nil。
参数 :
viewClass : 用于补充视图的类。
elementKind : 要创建的补充视图的类型。此值由布局对象定义。此参数不能为nil。
identifier : 要与指定类关联的重用标识符。此参数不能为nil,也不能为空字符串。
- (void)registerClass:(nullable Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
例如 :
[self.collectionView registerClass:[HeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"headerView"];
注:
UIKIT_EXTERN NSString *const UICollectionElementKindSectionHeader API_AVAILABLE(ios(6.0));
属性描述 : 标识给定节的标题的补充视图。
UIKIT_EXTERN NSString *const UICollectionElementKindSectionHeader API_AVAILABLE(ios(6.0));
UIKIT_EXTERN NSString *const UICollectionElementKindSectionFooter API_AVAILABLE(ios(6.0));
属性描述 : 标识给定节的页脚的补充视图。
UIKIT_EXTERN NSString *const UICollectionElementKindSectionFooter API_AVAILABLE(ios(6.0));
- (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
函数描述 : 返回由其标识符定位的可重用单元格对象,当要求为集合视图提供新单元格时,从数据源对象调用此方法。此方法在现有的单元格中出列,或者根据先前注册的类或NIB文件创建一个新的单元格。
在调用此方法之前,必须使用registerClass:forCellWithReuseIdentifier:或register nib:forCellWithReuseIdentifier:方法注册类或nib文件。
如果您为指定的标识符注册了一个类,并且必须创建一个新的单元格,则此方法通过调用其initWithFrame:方法初始化该单元格。对于基于nib的单元,此方法从提供的nib文件加载单元对象。如果现有的单元可用于重用,则该方法调用单元格的PraseReFuleRead方法。
参数 :
identifier : 指定单元格的重用标识符。此参数不能为nil。
indexPath : 指定单元格位置的索引路径。数据源在请求单元格时接收此信息,并应将其传递出去。此方法使用索引路径根据单元格在集合视图中的位置执行其他配置。
返回值 :有效的UICollectionViewCell对象。
- (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
例如 :
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
GoodsSalesDiscountItem *item = [collectionView dequeueReusableCellWithReuseIdentifier:@"item" forIndexPath:indexPath];
return item;
}
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
函数描述 : 返回可重用的补充视图,该视图按其标识符和类型定位。当要求为集合视图提供新的补充视图时,从数据源对象调用此方法。此方法可将现有视图排成队列,如果其中一个可用,或者根据先前注册的类或NIB文件创建一个新视图。
在调用此方法之前,必须使用registerClass:forSupplementaryViewOfKind:withReuseIdentifier:或registerNib:forSupplementaryViewOfKind:withReuseIdentifier:方法注册类或nib文件。您还可以使用registerClass:forDecorationViewOfKind:或registerNib:forDecorationViewOfKind:方法向布局对象注册一组默认补充视图。
参数 :
elementKind : 要检索的补充视图的类型。此值由布局对象定义。此参数不能为nil。
identifier : 指定视图的重用标识符。此参数不能为nil。
indexPath : 指定补充视图在集合视图中的位置的索引路径。数据源在请求视图时接收此信息,并应将其传递出去。此方法使用信息根据视图在集合视图中的位置执行附加配置。
返回值 : 有效的UICollectionReusableView对象。
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
例如 :
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
HeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"headerView" forIndexPath:indexPath];
return headerView;
}
return nil;
}
- (void)reloadData;
函数描述 : 重新加载集合视图的所有数据。当需要重新加载集合视图中的所有项时,请谨慎地调用此方法。这将导致集合视图放弃任何当前可见的项(包括占位符),并基于数据源对象的当前状态重新创建项。为了提高效率,集合视图只显示可见的单元格和补充视图。如果重新加载导致集合数据收缩,则集合视图会相应地调整其滚动偏移。不应在插入或删除项目的动画块中间调用此方法。插入和删除会自动导致集合的数据得到适当更新。
- (void)reloadData;
- (NSInteger)numberOfItemsInSection:(NSInteger)section;
函数描述 : 返回指定节中的项数。
参数 :
section : 要对其进行项目计数的节的索引。
返回值 :
- (NSInteger)numberOfItemsInSection:(NSInteger)section;
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 返回位于指定索引路径的项的布局信息。使用此方法检索特定项的布局信息。您应该始终使用此方法,而不是直接查询布局对象。
参数 :
indexPath : 项的索引路径。
返回值 : 项的布局属性,如果指定路径上不存在项,则为nil。
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
函数描述 : 返回指定补充视图的布局信息。使用此方法检索特定补充视图的布局信息。您应该始终使用此方法,而不是直接查询布局对象。
参数 :
kind : 指定所需布局属性的补充视图类型的字符串。布局类负责定义它们支持的补充视图的类型。
indexPath : 补充视图的索引路径。此值的解释取决于布局如何实现视图。例如,与节关联的视图可能只包含节的值。
返回值 : 返回补充视图的布局属性,如果指定的补充视图不存在,则返回nil。
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point;
函数描述 : 返回项目在集合视图中指定点的索引路径。此方法依赖关联的布局对象提供的布局信息来确定包含该点的项。
参数 :
point : 集合视图坐标系中的点。
返回值 : 在指定点上的项的索引路径,如果在指定点上找不到项,则为nil。
- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point;
- (nullable NSIndexPath *)indexPathForCell:(UICollectionViewCell *)cell;
函数描述 : 返回指定单元格的索引路径。
参数 :
cell : 需要其索引路径的单元格对象。
返回值 : 单元格的索引路径,如果指定的单元格不在集合视图中,则为nil。
- (nullable NSIndexPath *)indexPathForCell:(UICollectionViewCell *)cell;
- (nullable UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 返回指定索引路径处的可见单元格对象。
参数 :
indexPath : 指定单元格的节和项的索引路径。
返回值 : 对应索引路径处的单元格对象,如果单元格不可见或indexPath超出范围,则为nil。
- (nullable UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;
函数描述 : 滚动集合视图内容,直到指定的项目可见。
参数 :
indexPath : 要滚动到视图中的项的索引路径。
scrollPosition : 一个选项,指定滚动完成时项目应放置在何处。有关可能值的列表,参阅UICollectionViewScrollPosition。
animated : 指定“YES”设置滚动行为的动画,或指定“NO”立即调整滚动视图的可见内容。
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;
UICollectionViewScrollPosition的枚举值:
typedef NS_OPTIONS(NSUInteger, UICollectionViewScrollPosition) {
UICollectionViewScrollPositionNone = 0, //不要将项目滚动到视图中。
UICollectionViewScrollPositionTop = 1 << 0, //滚动以使项目位于集合视图边界的顶部。此选项与UICollectionViewScrollPositionCenteredVertical和UICollectionViewScrollPositionBottom选项互斥。
UICollectionViewScrollPositionCenteredVertically = 1 << 1, //滚动以使项目在集合视图中垂直居中。此选项与UICollectionViewScrollPositionTop和UICollectionViewScrollPositionBottom选项互斥。
UICollectionViewScrollPositionBottom = 1 << 2, //滚动以使项目位于集合视图边界的底部。此选项与UICollectionViewScrollPositionTop和UICollectionViewScrollPositionCenteredVertical选项互斥。
UICollectionViewScrollPositionLeft = 1 << 3, //滚动以使项目位于集合视图边界的左边缘。此选项与uiCollectionViewScrollPositionCenteredHorizontal和UICollectionViewScrollPositionRight选项互斥。
UICollectionViewScrollPositionCenteredHorizontally = 1 << 4, //滚动以使项目在集合视图中水平居中。此选项与UICollectionViewScrollPositionLeft和UICollectionViewScrollPositionRight选项互斥。
UICollectionViewScrollPositionRight = 1 << 5 //滚动以使项目位于集合视图边界的右边缘。此选项与UICollectionViewScrollPositionLeft和uiCollectionViewScrollPositionCenteredHorizontal选项互斥。
};
数据源UICollectionViewDataSource
采用UICollectionViewDataSource协议的对象负责提供集合视图所需的数据和视图。数据源对象表示应用程序的数据模型,并根据需要向集合视图提供信息。它还处理集合视图用于显示数据的单元格和补充视图的创建和配置。所有数据源对象都必须实现collectionView:numberOfItemsInSection:和collectionView:cellForItemAtIndexPath:方法。这些方法负责返回集合视图中的项目数以及项目本身。协议的其余方法是可选的,只有在集合视图将项目组织为多个节或为给定节提供页眉和页脚时才需要。
UICollectionViewDataSource中提供的常用函数:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
函数描述 : 询问数据源对象集合视图中的节数。如果不实现此方法,则集合视图使用默认值1。
参数 :
collectionView : 请求此信息的集合视图。
返回值 : collectionView中的节数。
//提供视图中节的个数,这个方法需要注意数据的行是否能与每一行有几个单元格整除,不能整除时要多加一行
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
函数描述 : 询问数据源对象指定节中的项目数。
参数 :
collectionView : 请求此信息的集合视图。
section : 标识collectionView中节的索引号。此索引值基于0。
返回值 : 节中的项数。
//每一节有几个单元格
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 向数据源对象询问与集合视图中指定项对应的单元格。此方法的实现负责为给定项创建、配置和返回适当的单元格。为此,可以调用集合视图的dequeueReusableCellWithReuseIdentifier:forIndexPath:方法并传递与所需单元格类型对应的重用标识符。该方法始终返回有效的单元格对象。接收单元格后,应设置与相应项的数据相对应的任何属性,执行任何其他所需配置,并返回单元格。
不需要在集合视图的边界内设置单元格的位置。集合视图使用每个单元格的布局对象提供的布局属性自动设置每个单元格的位置。
如果集合视图上的prefetchingEnabled设置为YES,则在单元格出现之前调用此方法。使用collectionView:willDisplayCell:forItemAtIndexPath:delegate方法对单元格的外观进行任何更改,以反映其视觉状态(如选择)。
此方法必须始终返回有效的视图对象。
参数 :
collectionView : 请求此信息的集合视图。
indexPath : 指定项位置的索引路径。
返回值 : 已配置的单元格对象。此方法不能返回nil,nil会引发异常。
//为某个单元格提供显示数据
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
函数描述 : 询问数据源对象提供要在集合视图中显示的补充视图。此方法的实现负责创建、配置和返回所请求的适当补充视图。为此,可以调用集合视图的dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:方法并传递与所需视图对应的信息。该方法始终返回有效的视图对象。接收到视图后,应设置与要显示的数据相对应的任何属性,执行任何其他所需配置,并返回视图。
不需要在集合视图的边界内设置补充视图的位置。集合视图使用其布局对象提供的布局属性设置每个视图的位置。
此方法必须始终返回有效的视图对象。如果在特定情况下不需要补充视图,则布局对象不应为该视图创建属性。或者,可以通过将相应属性的hidden属性设置为YES或将属性的alpha属性设置为0来隐藏视图。若要隐藏流布局中的页眉和页脚视图,还可以将这些视图的宽度和高度设置为0。
参数 :
collectionView : 请求此信息的集合视图。
kind : 要提供的那种补充视图。此字符串的值由支持补充视图的布局对象定义。
indexPath : 指定新补充视图位置的索引路径。
返回值 : 已配置的补充视图对象。此方法不能返回nil,nil会引发异常。
//为补充视图提供显示数据
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
}
创建cell
创建cell通过集合视图的dequeueReusableCellWithReuseIdentifier:forIndexPath:返回可重用单元格,
例如:
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
其中第一个参数是可重用单元格标识符,第二个参数是NSIndexPath类型,NSIndexPath是一种数据结构,是一种复杂多维数组结构,常用的属性是section和row两个,section是集合视图节索引,row是集合视图中单元格的索引。
委托协议UICollectionViewDelegate
UICollectionViewDelegate协议定义了一些方法,管理集合视图中项的选择和突出显示,并对这些项执行操作。本协议的方法都是可选的。该协议的许多方法都将NSIndexPath对象作为参数。为了支持集合视图,UIKit在NSIndexPath上声明了一个类别,使您能够获取表示的项索引和节索引,并从项和索引值构造新的索引路径对象。由于项位于其节中,因此通常必须先计算节索引号,然后才能通过其索引号标识项。配置集合视图对象时,请将委托对象分配给其委托属性。
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 询问委托选择指定的项是否可以被选择。当用户试图在集合视图中选择项目时,集合视图调用此方法。当您以编程方式设置选择时,它不会调用此方法。如果不实现此方法,则默认返回值为YES。
参数 :
collectionView : 询问选择是否应更改的集合视图对象。
indexPath : 要选择的单元格的索引路径。
返回值 : 如果可以选择项目,则为“YES”;如果不可以选择项目,则为“NO”。
//询问委托选择指定的项是否可以被选择
-(BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 告诉委托已选择指定索引路径处的项。当用户在集合视图中成功选择项目时,集合视图调用此方法。当您以编程方式设置选择时,它不会调用此方法。
collectionView : 通知您选择更改的集合视图对象。
indexPath : 选定单元格的索引路径。
//选择单元格之后触发
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 告诉委托指定路径处的项已被取消选择。当用户成功取消选择集合视图中的项目时,集合视图调用此方法。当您以编程方式取消选择项时,它不会调用此方法。
参数 :
collectionView : 通知您选择更改的集合视图对象。
indexPath : 取消选择的单元格的索引路径。
//取消选择单元格之后触发
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
}
例如创建一个可以多选的集合视图示例:
//多选要设置属性allowsMultipleSelection为YES
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
//获取当前要操作的Cell
self.cell = (YSLSeeEvaluateCell *)[collectionView cellForItemAtIndexPath:indexPath];
//可以对cell 的属性做一些设置
self.cell.title.textColor = [YSLUiUtils colorPrimary];
CALayer *layer = [self.cell.title layer];
[layer setBorderWidth:0.5f];
[layer setBorderColor:[YSLUiUtils colorPrimary].CGColor];
layer.cornerRadius = 3.0f;
}
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{
//获取当前要操作的Cell
self.cell = (YSLSeeEvaluateCell *)[collectionView cellForItemAtIndexPath:indexPath];
//可以对cell 的属性做一些设置
self.cell.title.textColor = [YSLUiUtils colorThree];
CALayer *layer = [self.cell.title layer];
[layer setBorderWidth:0.5f];
[layer setBorderColor:[YSLUiUtils colorSeven].CGColor];
layer.cornerRadius = 3.0f;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(8.0));
函数描述 : 告诉委托指定的单元格即将显示在集合视图中。集合视图在将单元格添加到其内容之前调用此方法。使用此方法检测单元格添加,而不是监视单元格本身以查看它何时出现。
参数 :
collectionView : 正在添加单元格的集合视图对象。
cell : 正在添加的单元格对象。
indexPath : 单元格表示的数据项的索引路径。
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(8.0));
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 告诉委托指定的单元格已从集合视图中移除。使用此方法可以检测单元格何时从集合视图中移除,而不是监视视图本身以查看其何时消失。
参数 :
collectionView : 移除单元格的集合视图对象。
cell : 已移除的单元格对象。
indexPath : 单元格表示的数据项的索引路径。
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(8.0));
函数描述 : 告诉委托指定的补充视图即将显示在集合视图中。集合视图在向其内容添加补充视图之前调用此方法。使用此方法检测视图添加,而不是监视视图本身以查看它何时出现。
参数 :
collectionView : 正在添加补充视图的集合视图对象。
view : 正在添加的视图。
elementKind : 补充视图的类型。此字符串由显示视图的布局定义。
indexPath : 补充视图表示的数据项的索引路径。
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(8.0));
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
函数描述 : 告诉委托指定的补充视图已从集合视图中移除。使用此方法可以检测何时从集合视图中移除辅助视图,而不是监视视图本身以查看它何时消失。
参数 :
collectionView : 移除辅助视图的集合视图对象。
view : 已移除的视图。
elementKind : 补充视图的类型。此字符串由显示视图的布局定义。
indexPath : 补充视图表示的数据项的索引路径。
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
UICollectionViewFlowLayout流布局管理器
UICollectionViewFlowLayout是一种流布局管理器,即从左到右从上到下布局,每行包含尽可能多的单元格,单元格可以是相同大小或不同大小。
流布局使用集合视图的委托对象来确定每个节和网格中项目、页眉和页脚的大小。该委托对象必须符合UICollectionViewDelegateFlowLayout协议。使用委托可以动态调整布局信息。例如,需要使用委托对象为网格中的项指定不同的大小。如果不提供委托,则流布局使用使用使用此类属性设置的默认值。
流布局使用一个方向上的固定距离和另一个方向上的可滚动距离来布局其内容。例如,在垂直滚动的网格中,网格内容的宽度限制为相应集合视图的宽度,而内容的高度则动态调整以匹配网格中的节数和项数。默认情况下,布局配置为垂直滚动,但可以使用scrollDirection属性配置滚动方向。
流布局中的每个节都可以有自己的自定义页眉和页脚。若要为视图配置页眉或页脚,必须将页眉或页脚的大小配置为非零。可以通过实现适当的委托方法或为headerReferenceSize和footerReferenceSize属性分配适当的值来完成此操作。如果页眉或页脚大小为0,则相应的视图不会添加到集合视图中。
UICollectionViewFlowLayout流布局管理器的一些常见属性
@property (nonatomic) CGFloat minimumLineSpacing;
属性描述 : 网格中项目行之间要使用的最小间距。如果委托对象未实现collectionView:layout:minimumLineSpacingForSectionAtIndex:方法,则流布局使用此属性中的值设置节中的行间距。
对于垂直滚动网格,此值表示连续行之间的最小间距。对于水平滚动网格,此值表示连续列之间的最小间距。此间距不应用于页眉与第一行之间或最后一行与页脚之间的间距。此属性的默认值为10.0。
@property (nonatomic) CGFloat minimumLineSpacing;
水平布局时,如图:
截屏2021-06-18上午10.42.48.png垂直布局时,如图:
截屏2021-06-18上午10.47.49.png@property (nonatomic) CGFloat minimumInteritemSpacing;
属性描述 : 要在同一行中的项之间使用的最小间距。如果委托对象未实现collectionView:layout:minimumitemSpacingForSectionAtIndex:方法,则流布局使用此属性中的值设置同一行中项目之间的间距。
对于垂直滚动网格,此值表示同一行中项目之间的最小间距。对于水平滚动网格,此值表示同一列中项目之间的最小间距。此间距用于计算一行可以容纳多少个项目,但在确定项目数之后,实际间距可能会向上调整。此属性的默认值为10.0。
@property (nonatomic) CGFloat minimumInteritemSpacing;
水平布局时,如图:
截屏2021-06-18上午11.11.35.png垂直布局时,如图:
截屏2021-06-18上午11.02.20.png注意minimumLineSpacing属性与minimumInteritemSpacing属性间的配合与其默认值,例如数据需要水平一行展示时,设置单元格间的间距需要使用minimumLineSpacing而非minimumInteritemSpacing。
@property (nonatomic) CGSize itemSize;
属性描述 : 用于单元格的默认大小。如果委托未实现collectionView:layout:sizeForItemAtIndexPath:方法,则流布局使用此属性中的值设置每个单元格的大小。这将导致所有单元格都具有相同的大小。默认大小值为(50.0,50.0)。
@property (nonatomic) CGSize itemSize;
@property (nonatomic) CGSize estimatedItemSize API_AVAILABLE(ios(8.0));
属性描述 : 集合视图中单元格的预估大小。当单元格动态调整其大小时,提供估计的单元格大小可以提高集合视图的性能。通过指定估计值,集合视图可以推迟确定其内容实际大小所需的某些计算。没有显示在屏幕上的单元格被假定为估计高度。
此属性的默认值为CGSizeZero。如果将其设置为任何其他值,则集合视图将使用单元格的preferredLayoutAttributesFittingAttributes:方法查询每个单元格的实际大小。如果所有单元格高度相同,请使用itemSize属性而不是此属性指定单元格大小。
@property (nonatomic) CGSize estimatedItemSize API_AVAILABLE(ios(8.0));
@property (nonatomic) UICollectionViewScrollDirection scrollDirection;
属性描述 : 网格的滚动方向。网格布局只沿着一个轴滚动,可以是水平方向,也可以是垂直方向。对于非滚动轴,该维度中集合视图的宽度用作内容的起始宽度。这个属性的默认值是UICollectionViewScrollDirectionVertical。
@property (nonatomic) UICollectionViewScrollDirection scrollDirection;
UICollectionViewScrollDirection的枚举值 :
typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {
UICollectionViewScrollDirectionVertical, //垂直滚动
UICollectionViewScrollDirectionHorizontal //水平滚动。
};
在Cell大小不同时,不同布局方向下Cell的排列如图:
水平方向:
截屏2020-09-19下午4.19.19.png垂直方向:
截屏2020-09-19下午4.21.47.png@property (nonatomic) CGSize headerReferenceSize;
属性描述 : 如果委托未实现collectionView:layout:referenceSizeForHeaderInSection:方法,则流布局对象使用此属性中设置的默认头大小。
在布局过程中,只使用与相应滚动方向相对应的大小。例如,对于垂直滚动方向,布局对象使用方法返回的高度值。(在这种情况下,页眉的宽度将设置为集合视图的宽度。)如果相应滚动维度中的大小为0,则不添加页眉。默认大小值为(0,0)。
@property (nonatomic) CGSize headerReferenceSize;
@property (nonatomic) CGSize footerReferenceSize;
属性描述 : 用于节页脚的默认大小。如果委托未实现collectionView:layout:referenceSizeForFooternSection:method,则流布局对象将使用为此属性设置的默认页脚大小。
在布局过程中,只使用与相应滚动方向相对应的大小。例如,对于垂直滚动方向,布局对象使用此属性指定的高度值。(在这种情况下,页脚的宽度将设置为集合视图的宽度。)如果相应滚动维度中的大小为0,则不添加页脚。默认大小值为(0,0)。
@property (nonatomic) CGSize footerReferenceSize;
@property (nonatomic) UIEdgeInsets sectionInset;
属性描述 : 用于在节中布局内容的边距:sectionInset,类型是UIEdgeInsets结构体。UIEdgeInsets包括:top(上边界),left(左边界),bottom(下边界),right(右边界)4个成员。UIEdgeInsetsMake函数可以创建UIEdgeInsets结构体实例。如果委托对象未实现collectionView:layout:insetForSectionAtIndex:方法,则流布局使用此属性中的值设置每个节的边距。页边距影响页眉视图的初始位置、每行项目两边的最小空间以及从最后一行到页脚视图的距离。边距插入不影响非滚动方向的页眉和页脚视图的大小。默认的边插入都设置为0。
@property (nonatomic) UIEdgeInsets sectionInset;
@property (nonatomic) BOOL sectionHeadersPinToVisibleBounds API_AVAILABLE(ios(9.0));
属性描述 : 当此属性为“YES”时,节标题视图将与内容一起滚动,直到它们到达屏幕顶部,此时它们将固定到集合视图的上限。每个滚动到屏幕顶部的新标题视图都会将先前固定的标题视图推离屏幕。此属性的默认值为“NO”。
@property (nonatomic) BOOL sectionHeadersPinToVisibleBounds API_AVAILABLE(ios(9.0));
@property (nonatomic) BOOL sectionFootersPinToVisibleBounds API_AVAILABLE(ios(9.0));
属性描述 : 一个布尔值,指示在滚动期间页脚是否固定到集合视图边界的底部。当此属性为“YES”时,节页脚视图将随内容一起滚动,直到它们到达屏幕底部,此时它们将固定到集合视图的下限。滚动到屏幕底部的每个新页脚视图都会将先前固定的页脚视图推离屏幕。此属性的默认值为“NO”。
@property (nonatomic) BOOL sectionFootersPinToVisibleBounds API_AVAILABLE(ios(9.0));
UICollectionViewDelegateFlowLayout提供的一些方法
- (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 询问委托指定项单元格的大小。如果不实现此方法,则流布局将使用其itemSize属性中的值来设置项的大小。此方法的实现可以返回一组固定的大小或根据单元格的内容动态调整大小。
流布局不会裁剪单元格边界以使其适合网格。因此,返回的值必须允许项目在集合视图中完全显示。例如,在垂直滚动的网格中,单个项的宽度不能超过集合视图本身的宽度(减去任何节插入)。但是,在滚动方向上,项可以大于集合视图,因为剩余的内容始终可以滚动到视图中。
参数 :
collectionView : 显示流布局的集合视图对象。
collectionViewLayout : 请求信息的布局对象。
indexPath :项的索引路径。
返回值 : 指定项的宽度和高度。两个值都必须大于0。
//动态设置每个Item的尺寸大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
}
- (UIEdgeInsets)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
函数描述 : 要求代理将边距应用于指定节中的内容。如果不实现此方法,则流布局将使用其sectionInset属性中的值来设置边距。此方法的实现可以返回一组固定的边距大小,或者为每个部分返回不同的边距大小。
节插入是仅应用于节中项目的边距。它们表示页眉视图和第一行项目之间以及最后一行项目和页脚视图之间的距离。它们还指示一行项目两边的间距。它们不会影响页眉或页脚本身的大小。
参数 :
collectionView : 显示流布局的集合视图对象。
collectionViewLayout : 请求信息的布局对象。
section : 需要插入的节的索引号。
返回值 : 应用于节中项目的边距。
//动态设置每个分区的EdgeInsets
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
}
- (CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
函数描述 : 询问委托指定节的连续行或列之间的间距。如果未实现此方法,则流布局将使用其minimumLineSpacing属性中的值来设置行之间的间距。此方法的实现可以为每个节返回固定值或不同的间距值。
对于垂直滚动网格,此值表示连续行之间的最小间距。对于水平滚动网格,此值表示连续列之间的最小间距。此间距不应用于页眉与第一行之间或最后一行与页脚之间的间距。
参数 :
collectionView : 显示流布局的集合视图对象。
collectionViewLayout : 请求信息的布局对象。
section : 需要行距的节的索引号。
返回值 : 分段中连续线之间的最小空间(以点为单位)。
//动态设置每行的间距大小
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
}
- (CGFloat)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
函数描述 : 要求委托指定节的行或列中连续项之间的间距。如果未实现此方法,则流布局将使用其minimumitemSpacing属性中的值来设置项之间的间距。此方法的实现可以为每个节的项返回固定值或不同的间距值。
对于垂直滚动网格,此值表示同一行中项目之间的最小间距。对于水平滚动网格,此值表示同一列中项目之间的最小间距。此间距用于计算一行可以容纳多少个项目,但在确定项目数之后,实际间距可能会向上调整。
参数 :
collectionView : 显示流布局的集合视图对象。
collectionViewLayout : 请求信息的布局对象。
section : 需要项间距的节的索引号。
返回值 : 分段线中连续项目之间的最小间距(以点为单位)。
//动态设置每个单元格的间距大小
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
}
- (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
函数描述 : 询问委托指定节中补充视图页眉视图的大小。如果不实现此方法,则流布局将使用其headerReferenceSize属性中的值设置页眉视图的大小。在布局过程中,只使用与相应滚动方向相对应的大小。例如,对于垂直滚动方向,布局对象使用方法返回的高度值。(在这种情况下,页眉的宽度将设置为集合视图的宽度。)如果相应滚动维度中的大小为0,则不添加页眉。
参数:
collectionView : 显示流布局的集合视图对象。
collectionViewLayout : 请求信息的布局对象。
section : 正在请求其标题大小的节的索引。
返回值 : 头部补充视图的大小。如果返回的值为size(0,0),则不添加头部补充视图。
//动态设置某个分区头视图大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
}
- (CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
函数描述 : 询问委托指定节中补充视图页脚视图的大小。如果不实现此方法,则流布局将使用其footerReferenceSize属性中的值来设置页脚视图的大小。在布局过程中,只使用与相应滚动方向相对应的大小。例如,对于垂直滚动方向,布局对象使用此属性指定的高度值。(在这种情况下,页脚的宽度将设置为集合视图的宽度。)如果相应滚动维度中的大小为0,则不添加页脚。
参数 :
collectionView : 显示流布局的集合视图对象。
collectionViewLayout : 请求信息的布局对象。
section : 正在请求其页脚大小的节的索引。
返回值 : 页脚的大小。如果返回的值为size(0,0),则不添加页脚。
//动态设置某个分区尾视图大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{
}
UICollectionViewLayout
用于为集合视图生成布局信息的抽象基类。布局对象的工作是确定单元格、补充视图和装饰视图在集合视图范围内的位置,并在需要时向集合视图报告该信息。然后,集合视图将提供的布局信息应用于相应的视图,以便在屏幕上显示它们。
必须子类化UICollectionViewLayout才能使用它。不过,在考虑子类化之前,应该查看UICollectionViewFlowLayout类,看看它是否能够适应布局的需求。
UICollectionViewLayout常用属性
@property (nonatomic, readonly, nullable) NSString *representedElementKind;
属性描述 : 目标视图的特定于布局的标识符。可以使用此属性中的值来标识与属性关联的辅助视图或装饰视图的特定用途。如果representedElementCategory属性包含值UICollectionElementCategoryCell,则此属性为nil。
@property(nonatomic, readonly) CGSize collectionViewContentSize;
属性描述 : 返回集合视图内容的宽度和高度。
@property(nonatomic, readonly) CGSize collectionViewContentSize;
collectionViewContentSize使用示例,例如获取集合视图内容的高度代码片段 :
- (void)setShopActivity:(NSArray<YSCResponseModelShopStreetShopActivityModel> *)shopActivity{
_shopActivity = shopActivity;
[self setNeedsLayout];
[self layoutIfNeeded];
[self.activityCollectionView reloadData];
CGFloat activityCollectionViewHeoght = self.activityCollectionView.collectionViewLayout.collectionViewContentSize.height;
[self.activityCollectionView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(activityCollectionViewHeoght);
}];
}
UICollectionViewLayout常用函数
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
函数描述 : 返回指定矩形中所有单元格和视图的布局属性。子类必须覆盖此方法并使用它来返回视图与指定矩形相交的所有项的布局信息。子类的实现应该返回所有可视元素的属性,包括单元格、补充视图和装饰视图。
在创建布局属性时,始终要创建一个attributes对象,该对象表示正确的元素类型(单元格、补充元素或装饰元素)。集合视图区分每种类型的属性,并使用这些信息来决定创建哪些视图以及如何管理它们。
参数 :
rect : 包含目标视图的矩形(在集合视图的坐标系统中指定)。
返回值 :UICollectionViewLayoutAttributes对象的数组,表示单元格和视图的布局信息。默认实现返回nil。
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
函数描述 : 返回项目在指定索引路径上的布局属性。子类必须重写此方法,并使用它返回集合视图中项的布局信息。使用此方法只能为具有相应单元格的项提供布局信息。不要将其用于补充视图或装饰视图。
参数 :
indexPath : 项的索引路径。
返回值 : 包含要应用于项单元格的信息的布局属性对象。
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)invalidateLayout;
函数描述 : 使当前布局失效并触发布局更新。可以随时调用此方法来更新布局信息。此方法使集合视图本身的布局无效,并立即返回。因此,可以从同一代码块多次调用此方法,而无需触发多个布局更新。实际布局更新发生在下一个视图布局更新周期中。如果重写此方法,则必须在实现中的某个点调用super。
- (void)invalidateLayout;
invalidateLayout使用示例,例如更新集合视图布局的代码片段 :
//获取集合视图布局
NHAlignmentFlowLayout *layout = (NHAlignmentFlowLayout *)self.collectionView.collectionViewLayout;
//判断是否显示页面边距与商品边距
BOOL hasBorder = (dataModel.style_border == 0) ? YES : NO;
if (!hasBorder) {
//不页面边距与商品边距
self.style_goods_item_margins = 0.0;
self.style_goods_page_margins = 0.0;
}
//行间距
layout.minimumLineSpacing = self.style_goods_item_margins;
//列间距
layout.minimumInteritemSpacing = self.style_goods_item_margins;
//cell大小
layout.itemSize = [(NSValue *)dataModel.extraInfo CGSizeValue];
//禁用动画转换视图
[UIView performWithoutAnimation:^{
//刷新集合视图
[self.collectionView reloadData];
//立即触发集合视图更新布局
[self.collectionView.collectionViewLayout invalidateLayout];
//设置集合视图内容内间距
self.collectionView.contentInset = UIEdgeInsetsMake(self.style_goods_page_margins
, self.style_goods_page_margins
, self.style_goods_page_margins
, self.style_goods_page_margins);
}];
UICollectionViewLayoutAttributes
管理集合视图中给定项的布局相关属性的布局对象。当集合视图要求布局对象创建该类的实例时会创建该类的实例。然后,集合视图使用布局信息在其边界内定位单元格和补充视图。
UICollectionViewLayoutAttributes常用属性
@property (nonatomic) CGRect frame;
属性描述 : 项的边框矩形。框架矩形以点为单位测量,并在集合视图的坐标系中指定。设置此属性的值还会设置“中心”和“大小”属性的值。
@property (nonatomic) CGRect frame;
@property (nonatomic) CGPoint center;
属性描述 : 项的中心点。中心点在集合视图的坐标系中指定。设置此属性的值也会更新frame属性中矩形的原点。
@property (nonatomic) CGPoint center;
@property (nonatomic) CGSize size;
属性描述 : 项的大小。设置此属性的值还会更改“ frame和bounds”属性返回的矩形的大小。
@property (nonatomic) CGSize size;
UICollectionView高度自适应
estimatedItemSize的推出,可以让CollectionView中也能让 cell 自适应内容大小,达到自动适应高度的预期效果。
UICollectionView的高度自适应的原理:
- CollectionView根据 layout 的 estimatedItemSize 算出估计的 contentSize,有了 contentSize CollectionView就开始显示
- CollectionView 在显示的过程中,即将被显示的 cell 根据 autolayout 的约束算出自适应内容的 size
- layout 从 CollectionView 里获取更新过的 size attribute
- layout 返回最终的 size attribute 给 CollectionView。CollectionView 使用这个最终的 size attribute 展示 cell
问题记录
1.关于布局方向为更改引发的问题:
因为懒,所以在项目中其他页面复制了一份UICollectionView的布局,因为布局方式是垂直布局未改为水平布局引发的问题:
屏幕快照 2019-10-13 下午2.15.22.png我勒个去,吓得我当场吃了一🐳,排查一下发现这个属性没改_flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;将其改为_flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;我就吧🐳放生了。。。
屏幕快照 2019-10-13 下午2.19.50.png2.关于集合视图使用Masonry设置约束,设置内容水平布局,第一次reloadData时cell不显示的问题:
Jietu20210405-222413.gif设置UICollectionView的代码如下:
///合并的分类集合视图
//初始化合并的分类集合视图布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
//设置水平滚动
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
//初始化合并的分类集合视图
_mergeStyleCollectionView = [[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:layout];
//设置合并的分类集合视图背景色
_mergeStyleCollectionView.backgroundColor = [UIColor whiteColor];
//设置合并的分类集合视图内容内边距
_mergeStyleCollectionView.contentInset = UIEdgeInsetsMake(0, 10, 0, 0);
//设置合并的分类集合视图数据源
_mergeStyleCollectionView.dataSource = self;
//设置合并的分类集合视图代理
_mergeStyleCollectionView.delegate = self;
//设置合并的分类集合视图不显示垂直滚动条
_mergeStyleCollectionView.showsVerticalScrollIndicator = NO;
//设置合并的分类集合视图不显示水平滚动条
_mergeStyleCollectionView.showsHorizontalScrollIndicator = NO;
//添加合并的分类集合视图
[self addSubview:_mergeStyleCollectionView];
//设置合并的分类集合视图约束
[_mergeStyleCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self);
make.top.bottom.equalTo(self);
make.right.equalTo(self.mas_right).offset(- 28);
}];
//注册商品子分类cell
[_mergeStyleCollectionView registerClass:[YSCGoodsSubCategoryItem class] forCellWithReuseIdentifier:YSC_GOODSSUBCATEGORY_ITEM];
问题出在UICollectionView设置约束的方式上,猜测可能是因为Masonry设置约束的方式上,UICollectionView在水平方向布局时,可能需要确切的高度,但使用Masonry时,第一次reloadData时,没有办法拿到UICollectionView的确切高度,导致cell无法显示,将约束改为如下代码:
//设置合并的分类集合视图约束
[_mergeStyleCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self);
make.top.equalTo(self);
make.right.equalTo(self.mas_right).offset(- 28);
make.height.mas_equalTo(45);
}];
UICollectionView的cell在第一次reloadData时能够正常显示:
Jietu20210405-223335.gif