LineLayout對于個別UICollectionViewLayoutAttributes的調整

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

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容