先来看效果
滑动到当前cell时,显示原尺寸大小;两边的按比例缩小;滑动时变大,最大为原尺寸大小。
思路
直接续承UICollectionViewFlowLayout,实现以下方法:
/**
* collectionView的显示范围发生改变的时候,调用下面这个方法是否重新刷新
*
* @return 是否重新刷新
*/
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
/**
* 布局的初始化操作
*/
- (void)prepareLayout
{
[super prepareLayout];
// 设置为水平滚动
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
}
/**
* 设置cell的显示大小
*
* @param rect 范围
*
* @return 返回所有元素的布局
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
// 获取计算好的布局属性
NSArray *arr = [[NSArray alloc]initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];
for (int i = 0; i < arr.count; i ++) {
UICollectionViewLayoutAttributes *att = arr[i];
//算比例
//拿到每个item的位置 算出itemCenterX 和collectionCenterX 的一个距离
CGFloat distance = ABS(att.center.x - self.collectionView.frame.size.width * 0.5 - self.collectionView.contentOffset.x);
CGFloat scale = 0.75;
CGFloat w = (self.collectionView.frame.size.width) * 0.5;
if (distance >= w) {
scale = scale;
}else{
scale = scale + (1- distance / w ) * 0.25;
}
att.transform = CGAffineTransformMakeScale(1.0, scale);
}
return arr;
}
//滑动完成后,会来到此方法 - 线性滑动
//proposedContentOffset 最后停止的 contentOffset
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
//proposedContentOffset滑动之后最后停的位置
CGRect rect;
rect.origin = proposedContentOffset;
rect.size = self.collectionView.frame.size;
//获取停止时,显示的cell的frame
NSArray<__kindof UICollectionViewLayoutAttributes *> *tempArray = [[NSArray alloc]initWithArray:[super layoutAttributesForElementsInRect:rect] copyItems:YES];
CGFloat gap = 1000;
CGFloat a = 0;
for (int i = 0; i < tempArray.count; i++) {
//判断和中心的距离,得到最小的那个
int edge = [tempArray[i] center].x - proposedContentOffset.x - self.collectionView.frame.size.width * 0.5;
if (gap > ABS(edge)) {
gap = ABS(edge);
a = edge;
}
}
CGPoint point = CGPointMake(proposedContentOffset.x + a , proposedContentOffset.y);
return point;
}
使用
初始化
-(UICollectionView *)collectionView{
if (_collectionView == nil) {
ELDiscoveryCarouselLayout * layout = [[ELDiscoveryCarouselLayout alloc] init];
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
//UIScrollViewDecelerationRateFast
_collectionView.decelerationRate = 0.9938;
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.backgroundColor = ELBlueColor;
// _collectionView.pagingEnabled = YES;
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:collectionCellId];
}
return _collectionView;
}
- 不要设置
pagingEnabled,否则targetContentOffsetForProposedContentOffset:withScrollingVelocity:将不起作用;decelerationRate是typedef CGFloat UIScrollViewDecelerationRate NS_TYPED_ENUM;类型的数据,它有两个值UIScrollViewDecelerationRateNormal和UIScrollViewDecelerationRateFast
| UIScrollViewDecelerationRate | 数值 |
|---|---|
| UIScrollViewDecelerationRateNormal | 0.998 |
| UIScrollViewDecelerationRateFast | 0.98999999999999999(0.99) |
所以我们也可以直接给decelerationRate赋值,范围是0.0~1.0,值越小,滑动越快,也就达到了pagingEnabled的效果了。
实现代理
#pragma mark ============ collectionview代理 ==============
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 13;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:collectionCellId forIndexPath:indexPath];
cell.contentView.backgroundColor = ELRedColor;
return cell;
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return CGSizeMake(ScreenW-40, SH(130));
}
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(10, 20, 10, 20);
}
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
return 10;
}
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 10;
}