效果如下:
collectionView的collectionViewLayout是自定义的,直接上代码:
@interface HMLineLayout : UICollectionViewFlowLayout
@end
@implementation HMLineLayout
static const CGFloat itemSizeWH = 100;
- (instancetype)init
{
if (self = [super init]) {
}
return self;
}
/** 只要显示的边界发生改变就重新布局:
* 内部会重新调用layoutAttributesForElementsInRect方法获得所有的cell的布局属性
*/
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
/**
* 用来设置collectionView停止滚动那一刻的位置
*
* @param proposedContentOffset 原本collectionView停止滚动那一刻的位置
* @param velocity 滚动速度
*/
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// 1.计算出scrollView最后会停留的范围
CGRect lastRect;
lastRect.origin = proposedContentOffset;
lastRect.size = self.collectionView.frame.size;
// 计算屏幕最中间的x
CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;
// 2.取出这个范围内的所有属性
NSArray *array = [self layoutAttributesForElementsInRect:lastRect];
// 3.遍历所有属性
CGFloat adjustOffsetX = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (ABS(attrs.center.x - centerX) < ABS(adjustOffsetX)) {
adjustOffsetX = attrs.center.x - centerX;
}
}
return CGPointMake(proposedContentOffset.x + adjustOffsetX, proposedContentOffset.y);
}
/**
* 一些初始化工作最好在这里实现
*/
- (void)prepareLayout
{
[super prepareLayout];
// 每个cell的尺寸
self.itemSize = CGSizeMake(itemSizeWH, itemSizeWH);
CGFloat inset = (self.collectionView.frame.size.width - itemSizeWH)*0.5;
self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
// 设置水平滚动
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.minimumLineSpacing = itemSizeWH;
// 每一个cell(item)都有自己的UICollectionViewLayoutAttributes
// 每一个indexPath都有自己的UICollectionViewLayoutAttributes
}
/** 有效距离:当item的centerX距离屏幕centerX在HMActiveDistance以内,才会开始放大,其他情况都在缩小 */
static CGFloat const HMActiveDistance = 150;
/** 缩放因素:值越大, item就会越大 */
static CGFloat const HMScaleFactor = 0.5;
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
// 1.计算可见的矩形框
CGRect visiableRect;
visiableRect.size = self.collectionView.frame.size;
visiableRect.origin = self.collectionView.contentOffset;
// 2.取得默认的cell的UICollectionViewLayoutAttributes
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 计算屏幕最中间的x
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;
// 3.遍历所有的布局属性
for (UICollectionViewLayoutAttributes *attrs in array) {
if (!CGRectIntersectsRect(visiableRect, attrs.frame)) continue;
// 每一个item的中点x
CGFloat itemCenterX = attrs.center.x;
// 差距越小, 缩放比例越大
// 根据跟屏幕最中间的距离计算缩放比例
CGFloat scale = 1 + HMScaleFactor * (1- (ABS(itemCenterX - centerX) / HMActiveDistance));
attrs.transform3D = CATransform3DMakeScale(scale, scale, 1.0);
}
return array;
}
@end