UICollectionView自定义布局掌握的五个方法:
// 作用:计算cell位置,只要计算一次,前提:cell的位置一开始就是固定
// 什么时候调用:第一次布局调用,每次刷新collectionView也会调用// 注意:必须要调用[super prepareLayout]
- (void)prepareLayout{
[super prepareLayout];
}
// UICollectionViewLayoutAttributes:cell的布局对象
// 每一个cell对应UICollectionViewLayoutAttributes
// UICollectionViewLayoutAttributes用来描述cell的布局
// UICollectionViewLayoutAttributes就是cell
// 作用:指定一个区域,就会返回这个区域内的所有cell布局
// 这个可以一次性返回所有cell布局,也可以分批方法
// 操作cell布局
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
// 获取显示范围
CGRect visableRect = self.collectionView.bounds;
NSArray *attrs = [super layoutAttributesForElementsInRect:visableRect];
for (UICollectionViewLayoutAttributes *attr in attrs) {
}
NSLog(@"%@",attrs);
return attrs;
}
// Invalidate:刷新
// 在拖动内容是否允许属性布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
// 什么时候调用:在拖动的时候,手指抬起调用
// 作用:返回最终偏移量,最终collectionView停到哪个位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// 第一个参数:就是最终偏移量, 手指快速拖动视图减速直到停止的偏移量 == proposedContentOffset参数
CGPoint targetOffset = [super targetContentOffsetForProposedContentOffset:proposedContentOffset withScrollingVelocity:velocity];
// self.collectionView.contentOffset 获取手指抬起时,collectionView的偏移量
NSLog(@"%@ %@", NSStringFromCGPoint(self.collectionView.contentOffset),NSStringFromCGPoint(proposedContentOffset));
return targetOffset;
}
// 作用:计算collectionView滚动范围
- (CGSize)collectionViewContentSize{
return [super collectionViewContentSize];
}
如下效果图所示,原理其实还是collectionView自定义其layout
自定义FlowLayout继承UICollectionViewFlowLayout,其.m文件实现如下:
@implementation FlowLayout
// 作用:计算cell位置,只要计算一次,前提:cell的位置一开始就是固定
// 什么时候调用:第一次布局调用,每次刷新collectionView也会调用
// 注意:必须要调用[super prepareLayout]
//- (void)prepareLayout
//{
// [super prepareLayout];
//
//}
// UICollectionViewLayoutAttributes:cell的布局对象
// 每一个cell对应UICollectionViewLayoutAttributes
// UICollectionViewLayoutAttributes用来描述cell的布局
// UICollectionViewLayoutAttributes就是cell
// 作用:指定一个区域,就会返回这个区域内的所有cell布局
// 这个可以一次性返回所有cell布局,也可以分批方法
// 操作cell布局
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
// 哪些cell需要进行缩放,显示cell才需要做缩放,获取显示出来cell布局,获取显示范围
// 问题:什么时候缩放,什么时候放大
// 离中心点越近,cell越大,离中心点越远,cell越小
// 缩放跟中心点成反比
// 计算中心点
// 获取显示范围
CGRect visableRect = self.collectionView.bounds;
NSArray *attrs = [super layoutAttributesForElementsInRect:visableRect];
;
for (UICollectionViewLayoutAttributes *attr in attrs) {
// 获取距离中心点的位置
CGFloat delta =fabs(attr.center.x - (self.collectionView.contentOffset.x + XMGScreenW * 0.5));
// 每个cell进行缩放 1 ~ 0.5
CGFloat scale = 1 - delta / (XMGScreenW * 0.5) * 0.25;
attr.transform = CGAffineTransformMakeScale(scale, scale);
}
return attrs;
}
// 作用:
// Invalidate:刷新
// 在拖动内容是否允许属性布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
// 什么时候调用:在拖动的时候,手指抬起调用
// 作用:返回最终偏移量,最终collectionView停到哪个位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// 定位:判断下谁离中心点近,就显示在中心位置
// 判断下最终显示那块区域
// 获取最终显示区域
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, XMGScreenW, MAXFLOAT);
// 获取最终显示区域下所有cell,去判断下哪个离中心点近
NSArray *attrs = [super layoutAttributesForElementsInRect:targetRect];
// 判断下哪个离中心点
CGFloat minDelta = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attr in attrs) {
// 获取中心点距离
CGFloat delta =attr.center.x - (self.collectionView.contentOffset.x + XMGScreenW * 0.5);
if (fabs(delta)
调用(特地介绍以下这种写法:其实这是C语言的逗号表达式,忘记是什么鬼请问度娘)
FlowLayout *layout = ({
layout = [[FlowLayout alloc] init];
// 设置cell尺寸
layout.itemSize = CGSizeMake(160, 160);
// 设置最小行间距为0
layout.minimumLineSpacing = 30;
// 设置滚动方向
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 设置额外滚动区域
CGFloat inset = (self.view.bounds.size.width - 160) * 0.5;
layout.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
layout;
});