首先我們來看一下 我們需要實現(xiàn)的最終效果圖

- 首先我們分析一下 這個布局是一個線性布局
- 先看LineLayout,它繼承了UICollectionViewFlowLayout這個Apple提供的基本的布局。它主要實現(xiàn)了單行布局,自動對齊到網格以及當前網格cell放大三個特性。
步驟
1.首先我們創(chuàng)建一個Layout繼承自UICollectionViewFlowLayout
- 其實下面在init里面做的操作最好放到-(void)prepareLayout中
-(id)init
{
self = [super init];
if (self) {
//設置每個item的大小 這個屬性最好在控制器中設置
self.itemSize = CGSizeMake150, 150);
//設置滾動方向
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
//設置內邊距
CGFloat insert =(self.collectionView.frame.size.width-self.itemSize.width)/2;
self.sectionInset =UIEdgeInsetsMake(0, insert, 0, insert);
//設置每行的最小間距
self.minimumLineSpacing = 50.0;
}
return self;
}
- 對齊到網格
/**
* 只要手一松開就會調用
* 這個方法的返回值,就決定了CollectionView停止?jié)L動時的偏移量
* proposedContentOffset這個是最終的 偏移量的值 但是實際的情況還是要根據(jù)返回值來定
* velocity 是滾動速率 有個x和y 如果x有值 說明x上有速度
* 如果y有值 說明y上又速度 還可以通過x或者y的正負來判斷是左還是右(上還是下滑動) 有時候會有用
*/
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
//計算出 最終顯示的矩形框
CGRect rect;
rect.origin.x =proposedContentOffset.x;
rect.origin.y=0;
rect.size=self.collectionView.frame.size;
NSArray * array = [super layoutAttributesForElementsInRect:rect];
// 計算CollectionView最中心點的x值 這里要求 最終的 要考慮慣性
CGFloat centerX = self.collectionView.frame.size.width /2+ proposedContentOffset.x;
//存放的最小間距
CGFloat minDelta = MAXFLOAT;
for (UICollectionViewLayoutAttributes * attrs in array) {
if (ABS(minDelta)>ABS(attrs.center.x-centerX)) {
minDelta=attrs.center.x-centerX;
}
}
// 修改原有的偏移量
proposedContentOffset.x+=minDelta;
//如果返回的時zero 那個滑動停止后 就會立刻回到原地
return proposedContentOffset;
}
- 當前item放大
/**
* 這個方法的返回值是一個數(shù)組(數(shù)組里存放在rect范圍內所有元素的布局屬性)
* 這個方法的返回值 決定了rect范圍內所有元素的排布(frame)
*/
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{ //獲得super已經計算好的布局屬性 只有線性布局才能使用
NSArray * array = [super layoutAttributesForElementsInRect:rect];
//計算CollectionView最中心的x值
#warning 特別注意:
CGFloat centetX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width/2;
for (UICollectionViewLayoutAttributes * attrs in array) {
//CGFloat scale = arc4random_uniform(100)/100.0;
//attrs.indexPath.item 表示 這個attrs對應的cell的位置
NSLog(@" 第%zdcell--距離:%.1f",attrs.indexPath.item ,attrs.center.x - centetX);
//cell的中心點x 和CollectionView最中心點的x值
CGFloat delta = ABS(attrs.center.x - centetX);
//根據(jù)間距值 計算cell的縮放的比例
//這里scale 必須要 小于1
CGFloat scale = 1 - delta/self.collectionView.frame.size.width;
//設置縮放比例
attrs.transform=CGAffineTransformMakeScale(scale, scale);
}
return array;
}
- 劃出范圍刷新布局
/*!
* 多次調用 只要滑出范圍就會 調用
* 當CollectionView的顯示范圍發(fā)生改變的時候,是否重新發(fā)生布局
* 一旦重新刷新 布局,就會重新調用
* 1.layoutAttributesForElementsInRect:方法
* 2.preparelayout方法
*/
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
參考Demo: GitHub地址
上一篇:UICollectionViewLayout布局詳解
下一篇:CircleLayout