思路
思路很简单,就是将每个item
的中心点的值center.x
,跟collectionView
的中心点的值center.x
做比较。距离越近的,缩放系数越大,距离远的,缩放系数越小。
写自定义的流水布局,必须知道的几个方法
-(void)prepareLayout;这个方法在 collection view 第一次展示的时候会调用,以及每次布局发生改变的时候也会调用。可以这这个方法里面,先预设一些属性,必须要调super
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;collection view的bounds发生改变的时候是否需要重新布局,一般为yes
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;这是最重要的方法了,这个方法返回每个item的布局属性。一个item对应一个UICollectionViewLayoutAttributes (item的size,缩放,透明度等等)。
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;这个方法表示collectionview滑动停止时,返回collectionview的偏移量。松手的那一刻调用。
接下来就是一些简单的计算了,直接上代码
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSLog(@"%s",__func__);
NSArray<UICollectionViewLayoutAttributes *> *attriArray = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];// 没有copy的话,会报警告
// 1.获取collectionview的中心点X的值
CGFloat collectionViewCenterX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
// 2.遍历每个item的布局属性,将每个item的中心点与collectionViewCenterX做比较
for (UICollectionViewLayoutAttributes *attribute in attriArray) {
// 2.1 计算每个item的中心点距离collectionViewCenterX的差值
CGFloat deltaX = ABS(attribute.center.x - collectionViewCenterX);
// 2.2 计算缩放系数,距离collectionViewCenterX越远的,就越小。这个自己看情况调整
CGFloat scale = 1 - deltaX / self.collectionView.frame.size.width;
attribute.transform = CGAffineTransformMakeScale(scale, scale);
}
return attriArray;
}
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// 1.因为滑动的时候,collectionview有惯性,所以要获取最终collectionview的布局属性
CGRect rect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.frame.size.width, self.collectionView.frame.size.height);
NSArray<UICollectionViewLayoutAttributes *> *attriArray = [[NSArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];
// 2.因为滑动的时候,collectionview有惯性,所以要获取最终collectionview的中心点X的值
CGFloat collectionViewCenterX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;
// 3.遍历每个item的布局属性,将每个item的中心点与collectionViewCenterX做比较,计算距离collectionViewCenterX最近的item
CGFloat deltaMinX = CGFLOAT_MAX;
for (UICollectionViewLayoutAttributes *attribute in attriArray) {
if (ABS(deltaMinX) > ABS(attribute.center.x - collectionViewCenterX)) {
deltaMinX = attribute.center.x - collectionViewCenterX;
}
}
proposedContentOffset.x += deltaMinX;
return proposedContentOffset;
}
以上我也是看了小码哥视频学的。demo点击这里