1.collectionview的用法很强大,我们平时用到的地方很多,但是大多数都是简单的使用,下面我来说一下复杂的用法,我也是从别的地方找来的 但是我弄明白了所以分享给大家 如果有什么不对的地方请给予指正 我将不胜感激!
- collectionView的创建
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, 200) collectionViewLayout:[[UICollectionViewFlowLayout alloc]init]];
collectionView.delegate = self;
collectionView.dataSource = self;
[collectionView registerNib:[UINib nibWithNibName:@"LDGItemCell" bundle:nil] forCellWithReuseIdentifier:ID];
[self.view addSubview:collectionView];
// 创建数据
for (NSInteger index = 1; index <= 20; index ++) {
NSString *str = [NSString stringWithFormat:@"%zd",index];
[self.dataArray addObject:str];
}
self.collectionView.backgroundColor = [UIColor redColor];
self.collectionView = collectionView;
[self.collectionView reloadData];
-
其实我个人觉得tableview 有时候和collectionview差不多 ,唯一最大的区别就是UICollectionViewLayout,就是这个UICollectionViewLayout 我们可以干很多的事情,下面我们来做一个这样的效果
1.png
这样的效果在优酷等等的视频软件上都会用到下面是具体的代码
#import "LDGlineFlowLayout.h"
@implementation LDGlineFlowLayout
-(void)prepareLayout {
[super prepareLayout];
self.itemSize = CGSizeMake(100, 100);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.minimumLineSpacing = 100;
self.sectionInset = UIEdgeInsetsMake(0, (self.collectionView.frame.size.width - self.itemSize.width)*0.5, 0, (self.collectionView.frame.size.width - self.itemSize.width)*0.5);
}
/**
这个方法是用来判断每次属性变化的时候都会返回
@param newBounds 新的位置变化
@return 是否都会会回调用
*/
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}
/**
最终停留的地方
@param proposedContentOffset 系统自动计算停留的地方
@param velocity 速度
@return 要停留的地方
*/
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
// 只需要计算当前与屏幕相交的即可 没有必要放大所有的
CGRect currentRect;
currentRect.size = self.collectionView.frame.size;
currentRect.origin = self.collectionView.contentOffset;
NSArray *array = [self layoutAttributesForElementsInRect:currentRect];
// 屏幕的中心点
CGFloat screenCenterX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;
// 计算最小值
CGFloat minF = MAXFLOAT;
CGFloat adjustF = 0;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (ABS(attrs.center.x - screenCenterX) <= minF) {
adjustF = attrs.center.x - screenCenterX;
}
}
return CGPointMake(proposedContentOffset.x + adjustF, proposedContentOffset.y);
}
/**
这个方法是间距变化返回每一个attr的数组
@param rect rect
@return 属性的数组
*/
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 只需要计算当前与屏幕相交的即可 没有必要放大所有的
CGRect currentRect;
currentRect.size = self.collectionView.frame.size;
currentRect.origin = self.collectionView.contentOffset;
// 拿到屏幕的中心点
CGFloat screenCenterX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (!CGRectIntersectsRect(currentRect, attrs.frame)) {
continue;
}
// 计算差值
CGFloat differX = ABS(attrs.center.x - screenCenterX);
// 计算需要放大的倍数
CGFloat scale = 1 + 0.7*(1- differX/self.collectionView.frame.size.width);
if (scale <= 1.3) {
scale = 1;
}
attrs.transform = CGAffineTransformMakeScale(scale, scale);
}
return array;
}
@end
下面是具体的解释 当这个方法:-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}返回yes的时候 系统滑动或者边距发生改变的时候就会调用- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect 调用非常的频发 我们拿到里边的UICollectionViewLayoutAttributes 来改变item的大小 但是这样的话很耗性能 我们只需要改变当前我们看到的地方的UICollectionViewLayoutAttributes就可以了 所以我们判断屏幕UICollectionViewLayoutAttributes的frame是否相交。
我们有一个功能是:停在最后的位置 但是系统最后的位置是任意的 所以我们重写这个方法 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity 经过我们找到距离屏幕中心点距离最小的位置的UICollectionViewLayoutAttributes 最后偏移到那个位置去就OK了。
-
第二个效果是做一个 这样的效果
1.png
- 具体实现的代码:
//
// LDGCircleLayout.m
// uicollectionView的联系
//
// Created by 刘殿阁 on 2018/4/7.
// Copyright © 2018年 刘殿阁. All rights reserved.
//
#import "LDGCircleLayout.h"
@implementation LDGCircleLayout
/**
这个方法是用来判断每次属性变化的时候都会返回
@param newBounds 新的位置变化
@return 是否都会会回调用
*/
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}
/**
返回的是每一个属性
@param indexPath indexPath
@return 属性
*/
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
NSInteger count = [self.collectionView numberOfItemsInSection:0];
// 计算角度
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attrs.center = CGPointMake(150 - 100*cos(indexPath.item*(M_PI*2/count)),100 - 100*sin(indexPath.item*(M_PI*2/count)));
attrs.size = CGSizeMake(50, 50);
return attrs;
}
/**
这个方法是间距变化返回每一个attr的数组
@param rect rect
@return 属性的数组
*/
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
NSMutableArray *dataArray = [NSMutableArray array];
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSInteger index = 0; index < count; index++) {
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
[dataArray addObject:attrs];
}
return dataArray;
}
@end
- 具体的解释:
这个LDGCircleLayout是继承的UICollectionViewLayout 而不是UICollectionViewFlowLayout因为 这个我们明显一看就不是流水布局,所以我们继承UICollectionViewLayout,这个就不具体解释了 很简单 需要实现这个- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath否则会报错澳 -
下面是卡片的动画效果
1.png
具体的代码实现如下:
#import "LDGStaticLayout.h"
@implementation LDGStaticLayout
/**
这个方法是用来判断每次属性变化的时候都会返回
@param newBounds 新的位置变化
@return 是否都会会回调用
*/
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}
/**
返回的是每一个属性
@param indexPath indexPath
@return 属性
*/
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
NSInteger count = [self.collectionView numberOfItemsInSection:0];
NSArray *angleArray = @[@(0),@(-0.2),@(-0.8),@(0.2),@(0.8)];
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attrs.center = CGPointMake(150, 100);
attrs.size = CGSizeMake(100, 100);
if (indexPath.item >= 5) {
attrs.hidden = YES;
}else{
attrs.hidden = NO;
attrs.transform = CGAffineTransformMakeRotation([angleArray[indexPath.item] floatValue]);
}
attrs.zIndex = count - indexPath.item;
return attrs;
}
/**
这个方法是间距变化返回每一个attr的数组
@param rect rect
@return 属性的数组
*/
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
NSMutableArray *dataArray = [NSMutableArray array];
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSInteger index = 0; index < count; index++) {
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
[dataArray addObject:attrs];
}
return dataArray;
}
@end
- 这个和圆环的差不多 实现原理 也是继承UICollectionViewLayout 因为流水布局办不到
-
下面实现一个瀑布流,大致的样子如下
1.png
- 具体的实现代码:
LDGPullViewLayout.h文件
#import <UIKit/UIKit.h>
@protocol LDGPullViewLayoutDelegate <NSObject>
@optional
/**
通过体格宽度来计算宽高比
@param indexPath indexPath
@return 返回宽高比
*/
- (CGFloat)receicewidthAndHeightScale:(NSIndexPath *)indexPath;
@end
@interface LDGPullViewLayout : UICollectionViewLayout
// 定义协议
@property (weak, nonatomic, nullable) id <LDGPullViewLayoutDelegate> layoutDelegate;
// 每一行之间的间距
@property (nonatomic, assign) CGFloat rowMargon;
// 每一列之间之间的间距
@property (nonatomic, assign) CGFloat columnMargon;
// 设置边距离
@property (nonatomic, assign) UIEdgeInsets layoutInset;
// 显示多少列
@property (nonatomic, assign) int columnCounts;
@end
LDGPullViewLayout.m文件实现
#import "LDGPullViewLayout.h"
@interface LDGPullViewLayout ()
@property (nonatomic, strong) NSMutableArray <UICollectionViewLayoutAttributes *>*attrArray;
@property (strong, nonatomic) NSMutableDictionary *minDic;
@end
@implementation LDGPullViewLayout
- (NSMutableArray *)attrArray {
if (!_attrArray) {
_attrArray = [NSMutableArray array];
}
return _attrArray;
}
-(NSMutableDictionary *)minDic {
if (!_minDic) {
_minDic = [[NSMutableDictionary alloc] init];
}
return _minDic;
}
-(instancetype)init {
if (self = [super init]) {
// 填写默认的行、列间距 默认的列数
self.rowMargon = 10;
self.columnMargon = 10;
self.columnCounts = 2;
self.layoutInset = UIEdgeInsetsMake(10, 10, 10, 10);
}
return self;
}
/**
初始化的相关的操作 这里最准确
*/
- (void)prepareLayout {
[super prepareLayout];
// 给最小值的字典设置值
for (NSInteger index = 0; index < self.columnCounts; index ++) {
self.minDic[@(index)] = @(self.layoutInset.top);
}
// 开始的时候初始化
[self.attrArray removeAllObjects];
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSInteger index = 0; index < count; index++) {
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
[self.attrArray addObject:attrs];
}
}
/**
这个方法用来计算ContentSize的大小 最终能够滑动的
@return size
*/
-(CGSize)collectionViewContentSize{
__block NSNumber *maxNumber = [NSNumber numberWithInt:0];
[self.minDic enumerateKeysAndObjectsUsingBlock:^(NSNumber* _Nonnull key, NSNumber* _Nonnull obj, BOOL * _Nonnull stop) {
if ([self.minDic[maxNumber] floatValue] < [obj floatValue]) {
maxNumber = key;
}
}];
return CGSizeMake(0, [self.minDic[maxNumber] floatValue] + self.layoutInset.bottom);
}
/**
间距发生变化的时候改变
@param newBounds newBounds
@return 对象本身
*/
//-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
// return YES;
//}
/**
返回每一个的item的属性
@param indexPath indexPath
@return item的属性
*/
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
// 宽度和高度
CGFloat attrW = (self.collectionView.frame.size.width - (self.layoutInset.left + self.layoutInset.right) - (self.columnCounts-1)*self.columnMargon)/self.columnCounts;
CGFloat scale = 0;
if ([self.layoutDelegate respondsToSelector:@selector(receicewidthAndHeightScale:)]) {
scale = [self.layoutDelegate receicewidthAndHeightScale:indexPath];
}
CGFloat attrH = attrW * scale;
// 假设最小值的那列是第0列,假设最小的列是第0列
__block NSNumber *minColumn = [NSNumber numberWithInt:0];
[self.minDic enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
if ([self.minDic[minColumn] floatValue] > [obj floatValue]) {
minColumn = key;
}
}];
CGFloat attrX = [minColumn integerValue] * (attrW + self.columnMargon) + self.layoutInset.left;
CGFloat attrY = [self.minDic[minColumn] floatValue] + self.rowMargon;
attrs.frame = CGRectMake(attrX, attrY, attrW, attrH);
self.minDic[minColumn] = @(CGRectGetMaxY(attrs.frame));
return attrs;
}
/**
间距发生变化就调用这个方法
@param rect rect
@return 数组
*/
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
return self.attrArray;
}
@end
- 特别说明:
1.我们计算的UICollectionViewLayoutAttributes的宽度和高度不难,因为宽度是由我们的列数确定的 ,后台会告诉我们宽度和高度 我们计算宽和高的比列就能计算出宽和高。
- 难的是计算x、y值 说实话 我开始想了半天没有想出来一个好的办法,后来经过查询 我看人家是用一个字典来计算的 ,也就是有多少列字典中有多少个key ,每个key存储的是每列的最大y值,我们经过字典便利来计算最小y值的那一列 从而确定x 和 y值
3.这个layout不用重写这个方法-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds,因为我们在prepare方法里全部初始化了。那就没有必要重复调用- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect这个方法了
4.值得注意的是collectionview不能用initwithframe 来进行创建 因为他要求layout必须不能为空。
- 关于瀑布流这里有一片不错的文章 瀑布流
- collectionview 的头部试图显示
大致分为几步:
1.创建基于UICollectionReusableView的cell
2.返回大小
3.实现UICollectionViewDelegateFlowLayout和UICollectionViewDelegate中的方法
具体的代码为:
JHHeaderFlowLayout *flowLayout = [[JHHeaderFlowLayout alloc] init];
flowLayout.itemSize = CGSizeMake((SCREEN_WIDTH -45)/2.0 , (SCREEN_WIDTH -45)/2.0 + 50);
flowLayout.minimumLineSpacing = 15;
flowLayout.minimumInteritemSpacing = 10;
self.collectionView.contentInset = UIEdgeInsetsMake(0, 15, 0, 15);
[self.collectionView registerNib:[UINib nibWithNibName:@"MRMSongListCell" bundle:nil] forCellWithReuseIdentifier:reuseSongListCellIndentifier];
[self.collectionView registerNib:[UINib nibWithNibName:@"MRMHeaderCollectionCell" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerCell_ID];
[self.collectionView setCollectionViewLayout:flowLayout];
#pragma mark - uicollectionFlowDelegate
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
return CGSizeMake(SCREEN_WIDTH, 200);
}
#pragma mark - uicollectionview 的 delegate
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
UICollectionReusableView *view = nil;
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
MRMHeaderCollectionCell *headerCell = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerCell_ID forIndexPath:indexPath];
return headerCell;
}
return view;
}
代码在(https://github.com/liudiange/practicePublic)中的
image.png
注意点为:
1.需要继承协议
image.png
2.我们在创建基于UICollectionReusableView的cell的时候 其中xcode有一个bug 就是你创建出来的cell (在有xib的前提下)不会主动继承你创建出来的类
image.png
需要你手动填写你自己的类,否则注册的时候说你的cell 不是你创建的那个类,我找了半天才找出来 可把我坑惨了 ,不信的话可以试试创建UITableViewCell勾选xib默认都是帮你继承你创建出来的类。
-
默认的情况下 collectionview的headerview是不会悬浮的,不想tableivew那样六,怎样办到悬浮 我在网上找了一个类
image.png
只要你的流水布局的layout继承这个类自动就会悬浮。
他的具体代码为:
JHHeaderFlowLayout.h文件
@interface JHHeaderFlowLayout : UICollectionViewFlowLayout
//默认为64.0, default is 64.0
@property (nonatomic, assign) CGFloat naviHeight;
@end
JHHeaderFlowLayout.m文件
#import "JHHeaderFlowLayout.h"
@implementation JHHeaderFlowLayout
-(instancetype)init
{
self = [super init];
if (self)
{
_naviHeight = 0.0;
}
return self;
}
/*
// 作用:返回指定区域的cell布局对象
// 什么时候调用:指定新的区域的时候调用
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
*/
- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect
{
//UICollectionViewLayoutAttributes:我称它为collectionView中的item(包括cell和header、footer这些)的《结构信息》
//截取到父类所返回的数组(里面放的是当前屏幕所能展示的item的结构信息),并转化成不可变数组
NSMutableArray *superArray = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
//创建存索引的数组,无符号(正整数),无序(不能通过下标取值),不可重复(重复的话会自动过滤)
NSMutableIndexSet *noneHeaderSections = [NSMutableIndexSet indexSet];
//遍历superArray,得到一个当前屏幕中所有的section数组
for (UICollectionViewLayoutAttributes *attributes in superArray)
{
//如果当前的元素分类是一个cell,将cell所在的分区section加入数组,重复的话会自动过滤
if (attributes.representedElementCategory == UICollectionElementCategoryCell)
{
[noneHeaderSections addIndex:attributes.indexPath.section];
}
}
//遍历superArray,将当前屏幕中拥有的header的section从数组中移除,得到一个当前屏幕中没有header的section数组
//正常情况下,随着手指往上移,header脱离屏幕会被系统回收而cell尚在,也会触发该方法
for (UICollectionViewLayoutAttributes *attributes in superArray)
{
//如果当前的元素是一个header,将header所在的section从数组中移除
if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader])
{
[noneHeaderSections removeIndex:attributes.indexPath.section];
}
}
//遍历当前屏幕中没有header的section数组
[noneHeaderSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop){
//取到当前section中第一个item的indexPath
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];
//获取当前section在正常情况下已经离开屏幕的header结构信息
UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
//如果当前分区确实有因为离开屏幕而被系统回收的header
if (attributes)
{
//将该header结构信息重新加入到superArray中去
[superArray addObject:attributes];
}
}];
//遍历superArray,改变header结构信息中的参数,使它可以在当前section还没完全离开屏幕的时候一直显示
for (UICollectionViewLayoutAttributes *attributes in superArray) {
//如果当前item是header
if ([attributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader])
{
//得到当前header所在分区的cell的数量
NSInteger numberOfItemsInSection = [self.collectionView numberOfItemsInSection:attributes.indexPath.section];
//得到第一个item的indexPath
NSIndexPath *firstItemIndexPath = [NSIndexPath indexPathForItem:0 inSection:attributes.indexPath.section];
//得到最后一个item的indexPath
NSIndexPath *lastItemIndexPath = [NSIndexPath indexPathForItem:MAX(0, numberOfItemsInSection-1) inSection:attributes.indexPath.section];
//得到第一个item和最后一个item的结构信息
UICollectionViewLayoutAttributes *firstItemAttributes, *lastItemAttributes;
if (numberOfItemsInSection>0)
{
//cell有值,则获取第一个cell和最后一个cell的结构信息
firstItemAttributes = [self layoutAttributesForItemAtIndexPath:firstItemIndexPath];
lastItemAttributes = [self layoutAttributesForItemAtIndexPath:lastItemIndexPath];
}else
{
//cell没值,就新建一个UICollectionViewLayoutAttributes
firstItemAttributes = [UICollectionViewLayoutAttributes new];
//然后模拟出在当前分区中的唯一一个cell,cell在header的下面,高度为0,还与header隔着可能存在的sectionInset的top
CGFloat y = CGRectGetMaxY(attributes.frame)+self.sectionInset.top;
firstItemAttributes.frame = CGRectMake(0, y, 0, 0);
//因为只有一个cell,所以最后一个cell等于第一个cell
lastItemAttributes = firstItemAttributes;
}
//获取当前header的frame
CGRect rect = attributes.frame;
//当前的滑动距离 + 因为导航栏产生的偏移量,默认为64(如果app需求不同,需自己设置)
CGFloat offset = self.collectionView.contentOffset.y + _naviHeight;
//第一个cell的y值 - 当前header的高度 - 可能存在的sectionInset的top
CGFloat headerY = firstItemAttributes.frame.origin.y - rect.size.height - self.sectionInset.top;
//哪个大取哪个,保证header悬停
//针对当前header基本上都是offset更加大,针对下一个header则会是headerY大,各自处理
CGFloat maxY = MAX(offset,headerY);
//最后一个cell的y值 + 最后一个cell的高度 + 可能存在的sectionInset的bottom - 当前header的高度
//当当前section的footer或者下一个section的header接触到当前header的底部,计算出的headerMissingY即为有效值
CGFloat headerMissingY = CGRectGetMaxY(lastItemAttributes.frame) + self.sectionInset.bottom - rect.size.height;
//给rect的y赋新值,因为在最后消失的临界点要跟谁消失,所以取小
rect.origin.y = MIN(maxY,headerMissingY);
//给header的结构信息的frame重新赋值
attributes.frame = rect;
//如果按照正常情况下,header离开屏幕被系统回收,而header的层次关系又与cell相等,如果不去理会,会出现cell在header上面的情况
//通过打印可以知道cell的层次关系zIndex数值为0,我们可以将header的zIndex设置成1,如果不放心,也可以将它设置成非常大,这里随便填了个7
attributes.zIndex = 7;
}
}
//转换回不可变数组,并返回
return [superArray copy];
}
//return YES;表示一旦滑动就实时调用上面这个layoutAttributesForElementsInRect:方法
- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound
{
return YES;
}
@end
- collectionview的footer 和header方式是一模一样的 。














网友评论