iOS吸附效果的實現 之 UICollectionView的使用全解

jopen 8年前發布 | 17K 次閱讀 iOS開發 移動開發

UICollectionView可以做很多的布局,在iOS開發中較為重要,所以這里就以實例來講解UICollectionView的使用進階。

注: 用StoryBoard拖出來的UICollectionView的布局就是流水布局,無法修改,所以如果要實現一些自定義的效果需要通過代碼創建UICollectionView

項目示例如下:效果為吸附的效果,App Store中也有類似的效果,就是單元格出來小于一半:則就讓其回退;如果大于一半:則就讓其直接移出界面顯示區域:

Demo下載地址: iOS_Demo

一些概念

UICollectionView中有個重要的內容 UICollectionViewLayout ,UICollectionView的顯示是由其布局文件決定的。

UICollectionViewFlowLayout :系統提供的流水布局,如果要自定義流水布局的效果可以自定義這個類。

布局決定每一個cell的尺寸,位置,間距等等。

每一個cell/item都有自己UICollectionViewLayoutAttributes

每一個indexPath也都有自己UICollectionViewLayoutAttributes

開始

所以這次做的吸附效果也完全是自定義了 UICollectionViewFlowLayout ,

下面對這個類的主要方法進行大體介紹:

  1. prepareLayout :一些初始化的工作最好這里完成,比如item的大小等等

    -(void)prepareLayout
    {
    [super prepareLayout];//需要調用super方法
    
    //初始化
    self.itemSize = CGSizeMake(90, 90);//設置item的大小
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;//設置滾動防線
    self.minimumLineSpacing = 10;//設置cell的間距
    self.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);//設置四周的間距
    }
  2. targetContentOffsetForProposedContentOffset :控制控制最后UICollectionView的最后去哪里,我們這里需要做的吸附效果的邏輯代碼就需要在這里完成。參數介紹 proposedContentOffset :原本UICollectionView停止滾動那一刻的位置; velocity :滾動速度

    -(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
    {
        //TODO
    }
  3. shouldInvalidateLayoutForBoundsChange :邊界發生改變時,是否需要重新布局,返回YES就需要重新布局(會自動調用layoutAttributesForElementsInRect方法,獲得所有cell的布局屬性)

    -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds

    {

    return YES;

    }

  4. layoutAttributesForElementsInRect :返回所有cell的布局屬性

    -(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        return [super layoutAttributesForElementsInRect:rect];
    }

方法介紹完畢,我們在 prepareLayout

-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
    //1.計算scrollview最后停留的范圍
    CGRect lastRect ;
    lastRect.origin = proposedContentOffset;
    lastRect.size = self.collectionView.frame.size;

    //2.取出這個范圍內的所有屬性
    NSArray *array = [self layoutAttributesForElementsInRect:lastRect];

    //起始的x值,也即默認情況下要停下來的x值
    CGFloat startX = proposedContentOffset.x;

    //3.遍歷所有的屬性
    CGFloat adjustOffsetX = MAXFLOAT;
    for (UICollectionViewLayoutAttributes *attrs in array) {
        CGFloat attrsX = CGRectGetMinX(attrs.frame);
        CGFloat attrsW = CGRectGetWidth(attrs.frame) ;

        if (startX - attrsX  < attrsW/2) {
            adjustOffsetX = -(startX - attrsX+ItemMaigin);
        }else{
            adjustOffsetX = attrsW - (startX - attrsX);
        }

        break ;//只循環數組中第一個元素即可,所以直接break了
    }
    return CGPointMake(proposedContentOffset.x + adjustOffsetX, proposedContentOffset.y);
}

這樣我們要做的吸附效果的Layout文件就完成了。

我們在初始化UICollectionView的時候選擇帶有Layout參數的init方法即可。

UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:rect collectionViewLayout:viscosityLayout];

Demo地址: iOS_Demo-自定義UICollectionView的布局

Demo下載地址: iOS_Demo

注:把Demo中的 ViewController.m 的33行

UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:rect collectionViewLayout:viscosityLayout];

改成//具體初始化的邏輯已經實現了。

UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:rect collectionViewLayout:flowLayout];

即可實現下圖所示的效果(cell滾動的時候,中間會慢慢變大,也有吸附效果,不過在最中心的cell才會吸附在中心),具體做法是在 layoutAttributesForElementsInRect 方法中修復了布局屬性,可下載Demo自行查看。

作者:Darren

微博:@IT_攻城師

github: @Darren90

博客: http://www.cnblogs.com/fengtengfei/

歡迎您的訪問...

來自: http://www.cnblogs.com/fengtengfei/p/5100925.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!