LineLayout對(duì)于個(gè)別UICollectionViewLayoutAttributes的調(diào)整

首先我們來看一下 我們需要實(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容