最近上班比較無聊,閒來無事就在網上隨便下項目看。數組
今天就來看看自定義瀑布流佈局。佈局
自定義瀑布流佈局主要是新建一個繼承自UICollectionViewFlowLayout的類,重點是實現該類中的一個方法:spa
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 在這個方法裏面,咱們要算出每一個item的文字和尺寸並返回給系統;code
當該類被咱們調用時系統會依次執行下列方法:blog
(1)- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds :當collectionView的顯示範圍發生改變的時候,是否須要從新刷新佈局
一旦從新刷新佈局,就會調用下面兩個方法;繼承
(2)- (void)prepareLayout :咱們通常在這裏執行一些初始化的操做圖片
(3)- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 在這個方法裏面,咱們要算出每一個item的文字和尺寸並賦值給每個 UICollectionViewLayoutAttributes,而後返回給系統, 系統根據這個數組的佈局屬性展現collectionView,到這裏自定義就搞定了。ci
固然,在這裏咱們也能夠監聽下面這個方法來控制congtenoffset:get
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocityit
下面現學現賣,自定義佈局實現以前項目的一個功能:
以前的一個項目有一個需求:要求作成以下的分頁效果
毫無疑問,這個功能確定用UICollectionView來搞定它,可是難點就是這種不連續的分頁效果,作起來比較麻煩。以前不知道重寫UICollectionViewFlowLayout,因而在控制器裏面直接監聽- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity 這個方法,這算起來就十分蛋疼了,不行你能夠試着玩玩。
可是!重點來了,若是經過繼承UICollectionViewFlowLayout自定義一個佈局,在這裏面監聽上面那個方法,那就爽歪歪了。咱們能夠輕鬆地拿到系統算好的佈局,在這個佈局的基礎上作微調就能夠了,核心代碼就幾句話:
- (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]; CGFloat collectionCenterX = self.collectionView.frame.size.width*0.5 + proposedContentOffset.x; CGFloat minDelta = MAXFLOAT; // 核心:判斷collectionView的中心離哪一個item更近就讓那個item顯示在中央 for (UICollectionViewLayoutAttributes *attrs in array) { if (fabs(minDelta)>fabs(attrs.center.x-collectionCenterX)) { minDelta = attrs.center.x-collectionCenterX; } } proposedContentOffset.x+=minDelta; return proposedContentOffset; }
這裏咱們只是拿到系統算好的佈局再作偏移,因此沒必要從新算佈局。
若是要作想天貓商品展現不等高的界面,如圖:
這種界面的思路就是佈局固定兩列,遍歷商品數據逐個把商品加到列高比較小的那一列,算出各個item的佈局屬性(咱們必須知道圖片的寬高比),這種算起來就稍微麻煩一點了。