自定義UICollectionViewFlowLayout

閑著沒(méi)事,無(wú)意間看到掌上英雄聯(lián)盟查看皮膚中CollectionView的效果,覺(jué)得很不錯(cuò),趁著機(jī)會(huì)也學(xué)習(xí)下UICollectionViewFlowLayout的自定義,先看效果:

查找資料,發(fā)現(xiàn)蘋果提供了2個(gè)關(guān)于Layout的demo,

Apple demo下載

LineLayoutDemo下載

這個(gè)基本上就是復(fù)制LineLayout的學(xué)習(xí),在原來(lái)的基礎(chǔ)上優(yōu)化了一點(diǎn)。

首先創(chuàng)建一個(gè)繼承與UICollectionViewFlowLayout的類,
我的.h

@interface GLCollectionViewFlowLayou : UICollectionViewFlowLayout

實(shí)現(xiàn)文件中主要有四個(gè)方法:

//可以在此方法中初始化你的layout
- (void)prepareLayout {
    //必須調(diào)用super
    [super prepareLayout];
}
//在這里改變布局 滑動(dòng)時(shí)會(huì)時(shí)時(shí)調(diào)用此方法
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
}
//替換最終滑動(dòng)的contentOffset, proposedContentOffset是預(yù)期滑動(dòng)停止的位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
}
// 當(dāng)collectionView bounds改變時(shí),是否重新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
    return YES;
}

蘋果的LineLayout在滑到第一個(gè)和最后一個(gè)的時(shí)候,有點(diǎn)問(wèn)題,不能更新到正確的位置。

在設(shè)置layout的時(shí)候設(shè)置UICollectionView的_collectionView.contentInset,設(shè)置如下:

    CGFloat left = CGRectGetWidth(self.collectionView.frame) / 2 - flowLayout.itemSize.width / 2;
    _collectionView.contentInset = UIEdgeInsetsMake(0, left, 0, left);

customLayout.m中,在targetContentOffsetForProposedContentOffset方法中處理第一個(gè)和最后一個(gè)的返回的contentOffset:

 //替換希望的contentOffset
    CGPoint actualPoint = CGPointMake(proposedContentOffset.x + minDistance, proposedContentOffset.y);
    
    //處理第一個(gè) 和 最后一個(gè)的contentOffset
    CGFloat minContentOffsetX = -floor(self.collectionView.contentInset.left);
    CGFloat maxContentOffsetX = floor(self.collectionView.contentSize.width - CGRectGetWidth(self.collectionView.frame) + self.collectionView.contentInset.right);
    actualPoint = actualPoint.x < minContentOffsetX ? CGPointMake(minContentOffsetX, actualPoint.y) : actualPoint;
    actualPoint = actualPoint.x > maxContentOffsetX ? CGPointMake(maxContentOffsetX, actualPoint.y) : actualPoint;
    return actualPoint;

這樣就OK了,滑倒第一個(gè)和最后一個(gè)也可以正常的顯示和滾動(dòng)了。

Demo地址:

點(diǎn)我哦


最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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