閑著沒事,無意間看到掌上英雄聯(lián)盟查看皮膚中CollectionView的效果,覺得很不錯,趁著機會也學(xué)習(xí)下UICollectionViewFlowLayout的自定義,先看效果:
查找資料备闲,發(fā)現(xiàn)蘋果提供了2個關(guān)于Layout的demo,
Apple demo下載
這個基本上就是復(fù)制LineLayout的學(xué)習(xí),在原來的基礎(chǔ)上優(yōu)化了一點捅暴。
首先創(chuàng)建一個繼承與UICollectionViewFlowLayout的類恬砂,
我的.h
@interface GLCollectionViewFlowLayou : UICollectionViewFlowLayout
實現(xiàn)文件中主要有四個方法:
//可以在此方法中初始化你的layout
- (void)prepareLayout {
//必須調(diào)用super
[super prepareLayout];
}
//在這里改變布局 滑動時會時時調(diào)用此方法
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
}
//替換最終滑動的contentOffset, proposedContentOffset是預(yù)期滑動停止的位置
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
}
// 當(dāng)collectionView bounds改變時,是否重新布局
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return YES;
}
蘋果的LineLayout在滑到第一個和最后一個的時候蓬痒,有點問題泻骤,不能更新到正確的位置。
在設(shè)置layout的時候設(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方法中處理第一個和最后一個的返回的contentOffset:
//替換希望的contentOffset
CGPoint actualPoint = CGPointMake(proposedContentOffset.x + minDistance, proposedContentOffset.y);
//處理第一個 和 最后一個的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了,滑倒第一個和最后一個也可以正常的顯示和滾動了亲轨。