iOS開發之窺探UICollectionViewController(三) :使用UICollectionView自定義瀑布流
上篇部落格的例項是自帶的UICollectionViewDelegateFlowLayout佈局基礎上來做的Demo, 詳情請看《iOS開發之窺探UICollectionViewController(二) –詳解CollectionView各種回撥》。UICollectionView之所以強大,是因為其具有自定義功能,這一自定義就不得了啦,自由度非常大,定製的高,所以功能也是灰常強大的。本篇部落格就不使用自帶的流式佈局了,我們要自定義一個瀑布流。自定義的瀑布流可以配置其引數: 每個Cell的邊距,共有多少列,Cell的最大以及最小高度是多少等。
一.先入為主
先來看一下不同配置引數下執行後的效果吧,每張截圖的列數和Cell之間的邊距都有所不同,瀑布流的列數依次為2,3,8。有密集恐懼證的童鞋就不要看這些執行效果圖了,真的會看暈的。下面這些執行效果就是修改不同的配置引數來進行佈局的。看圖吧,關於瀑布流的效果就不囉嗦了。以下的效果就是使用自定義佈局做的,接下來將會介紹一下其實現原理。
二. UICollectionViewLayout
在介紹上述效果實現原理之前,需要介紹一下UICollectionViewLayout。UICollectionView的自定義功能就是自己去實現UICollectionViewLayout的子類,然後重寫相應的方法來實現Cell的佈局,先介紹一下需要重寫的方法,然後再此方法上進行應用實現上述瀑布流。好,廢話少說,幹活走起。
1.佈局預載入函式
當佈局首次被載入時會呼叫prepareLayout函式,見名知意,就是預先載入佈局,在該方法中可以去初始化佈局相關的資料。該方法類似於檢視控制器的ViewDidLoad方法,稍後回用到該方法。
Objective-C1234 | // The collection view calls -prepareLayout once at its first layout as the first message to the layout instance.// The collection view calls -prepareLayout again after layout is invalidated and before requerying the layout information.// Subclasses should always call super if they override.-(void)prepareLayout; |
2.內容滾動範圍
下方是定義ContentSize的方法。該方法會返回CollectionView的大小,這個方法也是自定義佈局中必須實現的方法。說白了,就是設定ScrollView的ContentSize,即滾動區域。
Objective-C12 | // Subclasses must override this method and use it to return the width and height of the collection view’s content. These values represent the width and height of all the content, not just the content that is currently visible. The collection view uses this information to configure its own content size to facilitate scrolling.-(CGSize)collectionViewContentSize; |
3. 下方四個方法是確定佈局屬性的,下方第一個方法返回一個數組,該陣列中存放的是為每個Cell繫結的UICollectionViewLayoutAttributes屬性,便於在下面第二個方法中去定製每個Cell的屬性。第三個方法就是根據indexPath來獲取Cell所繫結的layoutAtrributes, 然後去更改UICollectionViewLayoutAttributes物件的一些屬性並返回,第四個是為Header View或者FooterView來定製其對應的UICollectionViewLayoutAttributes,然後返回。
Objective-C12345678 | // UICollectionView calls these four methods to determine the layout information.// Implement -layoutAttributesForElementsInRect: to return layout attributes for for supplementary or decoration views, or to perform layout in an as-needed-on-screen fashion.// Additionally, all layout subclasses should implement -layoutAttributesForItemAtIndexPath: to return layout attributes instances on demand for specific index paths.// If the layout supports any supplementary or decoration view types, it should also implement the respective atIndexPath: methods for those types.-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect;// return an array layout attributes instances for all the views in the given rect-(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath*)indexPath;-(UICollectionViewLayoutAttributes*)layoutAttributesForSupplementaryViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath*)indexPath;-(UICollectionViewLayoutAttributes*)layoutAttributesForDecorationViewOfKind:(NSString*)elementKind atIndexPath:(NSIndexPath*)indexPath; |
4.UICollectionViewLayoutAttributes
下方是UICollectionViewLayoutAttributes常用的屬性,你可以在上面第二個方法中去為下方這些屬性賦值,為Cell定製屬於自己的Attributes。由下方的屬性就對自定義佈局的的強大,在本篇部落格中只用到了下方的一個屬性,那就是frame。
Objective-C123456789 | @property(nonatomic)CGRectframe;@property(nonatomic)CGPointcenter;@property(nonatomic)CGSizesize;@property(nonatomic)CATransform3Dtransform3D;@property(nonatomic)CGRectbounds NS_AVAILABLE_IOS(7_0);@property(nonatomic)CGAffineTransformtransform NS_AVAILABLE_IOS(7_0);@property(nonatomic)CGFloatalpha;@property(nonatomic)NSIntegerzIndex;// default is 0@property(nonatomic,getter=isHidden)BOOLhidden;// As an optimization, UICollectionView might not create a view for items whose hidden attribute is YES |
三. UICollectionViewLayout的應用
經過上面的簡單介紹,想必對UICollectionViewLayout有一定的瞭解吧,UICollectionViewLayout中還有好多方法,以後用到的時候在給大家介紹。接下來要使用自定義佈局來實現瀑布流。我們需要在UICollectionViewLayout的子類中實現相應的佈局方法,因為UICollectionViewLayout是虛基類,是不能直接被例項化的,所以我們需要新建一個佈局類,這個佈局類繼承自UICollectionViewLayout。然後去實現上述方法,給每個Cell定製不同的UICollectionViewLayoutAttributes。好了還是拿程式碼說話吧。
1.重寫prepareLayout方法去初始化一些資料,該方法在CollectionView重新載入時只會呼叫一次,所以把一些引數的配置,計算每個Cell的寬度,每個Cell的高度等程式碼放在預處理函式中。在該函式中具體呼叫的函式如下所示:
Objective-C123456789101112131415 | #pragma mark -- 虛基類中重寫的方法/** * 該方法是預載入layout, 只會被執行一次 */-(void)prepareLayout{[superprepareLayout];[selfinitData];[selfinitCellWidth];[selfinitCellHeight];} |
2.返回內容的範圍,即為CollectionView設定ContentSize。ContentSize的Width就是螢幕的寬度,而ContentSize的高度是一列中最後一個Cell的Y座標加上其自身高度的最大值。在此函式中會呼叫求CellY陣列中的最大值。具體實現程式碼如下:
Objective-C123456789 | /** * 該方法返回CollectionView的ContentSize的大小 */-(CGSize)collectionViewContentSize{CGFloatheight=[self maxCellYArrayWithArray:_cellYArray];returnCGSizeMake(SCREEN_WIDTH,height);} |
3.下面的方法是為每個Cell去繫結一個UICollectionViewLayoutAttributes物件,並且以陣列的形式返回,在我們的自定義瀑布流中,我們只自定義了Cell的frame,就可以實現我們的瀑布流,UICollectionViewLayoutAttributes的其他屬性我們沒有用到,由此可以看出自定義Cell佈局功能的強大。
Objective-C1234567891011121314151617181920212223 | /** * 該方法為每個Cell繫結一個Layout屬性~ */-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{[selfinitCellYArray];NSMutableArray*array=[NSMutableArrayarray];//add cellsfor(inti=0;i){NSIndexPath*indexPath=[NSIndexPath indexPathForItem:i inSection:0];UICollectionViewLayoutAttributes*attributes=[self layoutAttributesForItemAtIndexPath:indexPath];[array addObject:attributes];}returnarray;} |
4. 通過下述方法設定每個Cell的UICollectionViewLayoutAttributes物件的引數,為了實現瀑布流所以我們只需要設定每個Cell的frame即可。每個cell的frame的確定是以列來定的,有所在列的上個Cell的Y座標來確定下個cell的位置。瀑布流實現關鍵點如下:
(1)Cell寬度計算:如果瀑布流的列數和Cell的Padding確定了,那麼每個Cell的寬度再通過螢幕的寬度就可以計算出來了。
(2)Cell高度計算:通過隨機數生成的高度
(3)Cell的X軸座標計算:通過列數,和Padding,以及每個Cell的寬度很容易就可以計算出每個Cell的X座標。
(4)Cell的Y軸座標計算:通過Cell所在列的上一個Cell的Y軸座標,Padding, 和 上一個Cell的高度就可以計算下一個Cell的Y座標,並記錄在Y座標的陣列中了。
Objective-C123456789101112131415161718192021222324252627 | /** * 該方法為每個Cell繫結一個Layout屬性~ */-(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath*)indexPath{UICollectionViewLayoutAttributes*attributes=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];CGRectframe=CGRectZero;CGFloatcellHeight=[_cellHeightArray[indexPath.row] floatValue];NSIntegerminYIndex=[self minCellYArrayWithArray:_cellYArray];CGFloattempX=[_cellXArray[minYIndex] floatValue];CGFloattempY=[_cellYArray[minYIndex] floatValue];frame=CGRectMake(tempX,tempY,_cellWidth,cellHeight);//更新相應的Y座標_cellYArray[minYIndex]=@(tempY+cellHeight+_padding);//計算每個Cell的位置attributes.frame=frame;returnattributes;} |
5. initData方法主要是對資料進行初始化,在本篇部落格中為了先實現效果,我們暫且把資料給寫死。下篇部落格會在本篇部落格中的基礎上進行優化和改進,這些配置引數都會在Delegate中提供,便於靈活的去定製屬於你自己的瀑布流。本篇部落格中Demo的配置項先寫死就OK了,還是那句話,下篇部落格中會給出一些相應的代理,來定製我們的瀑布流。
Objective-C12345678910111213 | /** * 初始化相關資料 */-(void)initData{_numberOfSections=[self.collectionView numberOfSections];_numberOfCellsInSections=[self.collectionView numberOfItemsInSection:0];//通過回撥獲取列數_columnCount=5;_padding=5;_cellMinHeight=50;_cellMaxHeight=150;} |
6.下方的方法是根據Cell的列數來求出Cell的寬度。因為Cell的寬度都是一樣的,每個Cell的間隔也是一定的。例如有5列Cell, 那麼Cell中間的間隔就有4(5-1)個,那麼每個Cell的寬度就是螢幕的寬度減去所有間隔的寬度,再除以列數就是Cell的寬度。如果沒聽我囉嗦明白的話,直接看程式碼吧,並不複雜。每個Cell的寬度和間隔確定了,那麼每個Cell的X軸座標也就確定了。程式碼如下:
Objective-C1234567891011121314151617 | /** * 根據Cell的列數求出Cell的寬度 */-(void)initCellWidth{//計算每個Cell的寬度_cellWidth=(SCREEN_WIDTH-(_columnCount-1)*_padding)/_columnCount;//為每個Cell計算X座標_cellXArray=[[NSMutableArrayalloc] initWithCapacity:_columnCount];for(inti=0;i){CGFloattempX=i *(_cellWidth+_padding);[_cellXArray addObject:@(tempX)];}} |
7. 根據Cell的最小高度和最大高度來利用隨機數計算每個Cell的高度,把每個Cell的高度記錄在陣列中,便於Cell載入時使用。具體程式碼如下:
相關推薦
iOS開發之窺探UICollectionViewController(三) :使用UICollectionView自定義瀑布流
上篇部落格的例項是自帶的UICollectionViewDelegateFlowLayout佈局基礎上來做的Demo, 詳情請看《iOS開發之窺探UICollectionViewController(二) –詳解CollectionView各種回撥》。UICollectionV
iOS開發之窺探UICollectionViewController(五):一款炫酷的圖片瀏覽元件
本篇部落格應該算的上CollectionView的高階應用了,從到今天的(五),可謂是由淺入深的窺探了一下UICollectionView的用法,這些用法不僅包括SDK中自帶的流式佈局(UICollectionViewDelegateFlowLayout)而且介紹瞭如何根據你的
iOS開發之窺探UICollectionViewController(二) :詳解CollectionView各種回撥
UICollectionView的佈局是可以自己定義的,在這篇部落格中先在上篇部落格的基礎上進行擴充,我們先使用UICollectionViewFlowLayout,然後好好的介紹一下UICollectionView的一些回撥方法,主要包括UICollectionViewDat
iOS開發之窺探UICollectionViewController(一) :Ready Your CollectionViewController
之前用CollectionViewController只是皮毛,一些iOS從入門到精通的書上也是泛泛而談。這幾天好好的搞了搞蘋果的開發文件上CollectionViewController的內容,親身體驗了一下CollectionViewController的強大,之前一直認為
iOS開發之窺探UICollectionViewController(四) --一款功能強大的自定義瀑布流
在上一篇部落格中,自定義瀑布流的列數,Cell的外邊距,Cell的最大以及最小高度是在我們的佈局檔案中是寫死的,換句話說也就是不可配置的。為了循序漸進,由淺入深呢,上篇部落格暫且那麼寫。不過那樣寫太過死板,本來使用起來比較靈活的自定義佈局,如果把其配置引數給寫死了,就相當於在籠
ios開發之--仿(微信)自定義表情鍵盤
lai signed avi 創建 不能 url div load mps 先附上demo:https://github.com/hgl753951/CusEmoji.git 效果圖如下: 先說下具體的實現功能: 1,本地加載了一些H5的代碼,直接使用webview的lo
iOS開發之如何在NSURLRequest中設定自定義header請求頭
在使用百度API的時候需要在HTTP請求頭中增加一個apikey,後來我查到已經有相關文章了:http://ju.outofmemory.cn/entry/136630 不過此文章寫得讓人有點看不明白,所以我根據此文章重新介紹如何在NSURLRequest設定自定義請求頭
iOS開發之百度地圖大頭針的自定義解決方法
方法1 - (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>
IOS開發之HomeKit(三)
上一篇文章我們只是介紹瞭如何獲取新增移除home和room物件,這篇繼續往下走。還需要說的一點就是,我們所新增或者移除的這些homeKit物件都是會儲存在一個共享的homeKit資料庫中的。可以被多個應用程式通過homeKit框架訪問,我們在自己寫的hom
Android開發之漫漫長途 番外篇——自定義View的各種姿勢2
是個 pub water 常用 getchild mod one 它的 sdn 該文章是一個系列文章,是本人在Android開發的漫漫長途上的一點感想和記錄,我會盡量按照先易後難的順序進行編寫該系列。該系列引用了《Android開發藝術探索》以及《深入理解Android 卷
Docker系列(三):docker自定義容器映象
將容器程式設計映象: docker commit [repo:tag] 網上有這句話:當我們在製作自己的映象的時候,會在container中安裝一些工具、修改配置,如果不做commit儲存 起來,那麼container停止以後再啟動,這些更改就消失了。 docker create
angularJS學習之路(三十)---自定義指令---templateUrl
第一種寫法: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title&
iOS開發UI篇—自定義瀑布流控制元件(蘑菇街資料重新整理操作)
1 // 2 // YYWaterflowView.m 3 // 06-瀑布流 4 // 5 // Created by apple on 14-7-29. 6 // Copyright (c) 2014年 wendingding. All rights reserved.
.Net微信網頁開發之使用微信JS-SDK自定義微信分享內容
第一步、微信JS-SDK的使用步驟,配置資訊的生成獲取講解: 關於JS-SDK的使用步驟和timestamp(時間戳),nonceStr(隨機串),signature(簽名),access_token(介面呼叫憑據)生成獲取的詳細說明在這裡:https://www.cnblogs.com/Can-day
iOS開發之網路程式設計篇三:同步,非同步請求差異及用法
在網路請求方式上,有同步和非同步之分,相關內容涉及到執行緒部分知識,這一節咱們需要知道如何去傳送一個同步或者非同步的請求,以及它們二者的區別。 一、同步請求 在網路程式設計第二篇,咱們寫的get,post請求使用的都是同步請求,那結合同步非同步、get/post組
iOS開發之使用UICollectionView實現美團App的分類功能【偶現大眾點評App的一個小bug】
sso leg 一個 borde spa line 註意 oba alt 郝萌主傾心貢獻,尊重作者的勞動成果,請勿轉載。假設文章對您有所幫助,歡迎給作者捐贈,支持郝萌主,捐贈數額任意,重在心意^_^ 我要捐贈: 點擊捐贈Cocos2d-X源代碼下載:點我傳送遊戲官方下載
iOS開發之runtime(一):runtime除錯環境搭建
本系列部落格是本人的原始碼閱讀筆記,如果有iOS開發者在看runtime的,歡迎大家多多交流。為了方便討論,本人新建了一個微信群(iOS技術討論群),想要加入的,請新增本人微信:zhujinhui207407,【加我前請備註:ios 】,本人部落格http://www.kyson.cn 也在不停的更新中,歡迎
iOS開發之Weex嵌入已有應用(三)
前言 1.官方環境部署 2.純Weex開發簡單的App 前兩個文章介紹了一下我遇到看到的一些需要注意的東西,其實按照官方的或者其他博主寫的Weex文章,雖然不多,但是很多人都是用嵌入應用的方式做專案的,如果純Weex開發,可以點選上面的文章,自己寫著玩應該還不錯,下面介紹下自己如何整合到專
iOS開發之再探多執行緒程式設計:Grand Central Dispatch詳解
Swift3.0相關程式碼已在github上更新。之前關於iOS開發多執行緒的內容釋出過一篇部落格,其中介紹了NSThread、操作佇列以及GCD,介紹的不夠深入。今天就以GCD為主題來全面的總結一下GCD的使用方式。GCD的歷史以及好處在此就不做過多的贅述了。本篇部落格會通過一系列的例項來好好的總結一下GC
iOS開發之三個Button實現圖片無限輪播(參考手機淘寶,Swift版)
這兩天使用Reveal工具檢視"手機淘寶"App的UI層次時,發現其圖片輪播使用了三個UIButton的複用來實現的圖片迴圈無縫滾動。於是乎就有了今天這篇部落格,看到“手機淘寶”這個幻燈片的UI層級時,就想要動手使用三個Button來實現一下,當然本篇部落格使用是Swift語言,思路就是使用三個Button進