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

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