1. 程式人生 > >三種實現iOS瀑布流的思路總結

三種實現iOS瀑布流的思路總結

瀑布流介紹

瀑布流可以在保證圖片原始比例的情況下,靈活的展現內容,相對於傳統的使用相同大小的網格展現大量圖片,效果上要好上很多,而實現瀑布流的方式有很多種,網上比較流行的有三種實現方式。 
1,使用UIScrollView,主要技術點在於檢視的重用。 
2,使用UITableView,這種方式應該是最易想到的,因為需要展現幾列就用幾個tabelview就ok了,而且不需要考慮重用,因為蘋果已經做好了,只需要考慮如何在幾列tabelView滑動的時候,保持同步不出現BUG。 
3,使用UICollectionView,UICollectionView在iOS6中第一次被介紹,它與UITableView有許多相似點,但它多了一個佈局類,而實現瀑布流,就與這個佈局類有關。此種方式實現,也不需要考慮檢視重用。

UITableView的重用機制做瀑布流思路

  1. 總先做成幾列是事先要清楚,有多少條記錄,這個可以從json或者xml中讀取後知道(json或xml最好將圖片的高度和寬度也顯示出來,便於後面用到。
  2. 假設要做成3列,就用三個uitableview,寬度平均,高度動態,頁面高度取uitableview中最高的。
  3. 三個uitableview初始化的時候用到tag(我越來越覺得tag在ios中的用處很大,就像js中讀取html控制元件中的id一樣),然後 showsVerticalScrollIndicator和scrollEnabled設為no,separatorStyle設為 UITableViewCellSeparatorStyleNone,新增到UIview中。

下面詳細講一下用UICollectionView做瀑布流

1.故事板中拖拽一個UICollectionView放在檢視中

2.新建一個繼承子UICollectionViewCell的子類MyCollectionViewCell,將單元格的Class選定為MyCollectionViewCell,並且設定Identifier為MyCell。

3.實現UICollectionViewDelegate,UICollectionViewDataSource,設定區域,設定區域中的Item個數,生成可複用的單元格:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">-(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSInteger</span>)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
}

-(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSInteger</span>)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSInteger</span>)section{
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSIndexPath</span> *)indexPath{
    MyCollectionViewCell *myCell=[collectionView dequeueReusableCellWithReuseIdentifier:
                                  @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"MyCell"</span> forIndexPath:indexPath];
    [myCell setBackgroundColor:[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIColor</span> greenColor]];
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>  myCell;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

viewDidLoad中設定一下資料來源和代理:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.collectionView</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.delegate</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.collectionView</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.dataSource</span>=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.collectionView</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.backgroundColor</span>=[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIColor</span> whiteColor];</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

最終效果: 
這裡寫圖片描述

進行masonry layout (佈局)

很多情況下所有的單元格的寬度是一定的,只是高度不確定,這就是有些人說的定寬不定高,主要是從視覺上的美感來看,當然我們可以通過實現

<code class="hljs erlang has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">UICollectionViewDelegateFlowLayout</span>去改變單元格大小:
<span class="hljs-pp" style="box-sizing: border-box;">-<span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-variable" style="box-sizing: border-box;">CGSize</span>)</span>collectionView:<span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-variable" style="box-sizing: border-box;">UICollectionView</span> *)</span>collectionView layout:<span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-variable" style="box-sizing: border-box;">UICollectionViewLayout</span> *)</span>collectionViewLayout sizeForItemAtIndexPath:<span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-variable" style="box-sizing: border-box;">NSIndexPath</span> *)</span>indexPath{

    CGFloat height=100+<span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(<span class="hljs-function_name" style="box-sizing: border-box;">arc4random</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">%100);</span>
    return  <span class="hljs-variable" style="box-sizing: border-box;">CGSizeMake</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>, height)</span>;

}</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

通過效果我們可以發現,同一行的單元格的圓心所在的Y軸座標都是一樣的: 
這裡寫圖片描述 
設定儲存所有高度的陣列: 
//儲存所有的高度的陣列

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span>,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>) <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSMutableArray</span>  *heightArr;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

將高度新增到陣列中:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">-(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">CGSize</span>)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSIndexPath</span> *)indexPath{

    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">CGFloat</span> height=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>+(arc4random()%<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">160</span>);
    [<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.heightArr</span> addObject:[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> stringWithFormat:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%f"</span>,height]];

    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>  CGSizeMake(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>, height);

}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

修改每一行單元格的位置:

<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSIndexPath</span> *)indexPath{

    MyCollectionViewCell *myCell=[collectionView dequeueReusableCellWithReuseIdentifier:
                    @<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"MyCell"</span> forIndexPath:indexPath];

    [myCell setBackgroundColor:[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIColor</span> redColor]];
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSInteger</span> remainder=indexPath<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.row</span>%<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;

    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSInteger</span> currentRow=indexPath<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.row</span>/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;

    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">CGFloat</span>   currentHeight=[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.heightArr</span>[indexPath<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.row</span>] floatValue];


    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">CGFloat</span> positonX=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>*remainder+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>*(remainder+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);
    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">CGFloat</span> positionY=(currentRow+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>;
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSInteger</span> i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; i<currentRow; i++) {

        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSInteger</span> position=remainder+i*<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;

        positionY+=[<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">self</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.heightArr</span>[position] floatValue];
    }
   myCell<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">.frame</span> = CGRectMake(positonX, positionY,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,currentHeight) ;


    NSUInteger *randomNumber=arc4random_uniform(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">9</span>);

    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *girlFilename = [<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> stringWithFormat:@<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Girl%lu.jpg"</span>, (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>)randomNumber];

    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImageView</span> *imageView = [[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImageView</span> alloc] initWithImage:[<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">UIImage</span> imageNamed:girlFilename]];


    [myCell setBackgroundView:imageView];
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span>  myCell;

}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li></ul>

最終效果 
這裡寫圖片描述

iOS瀑布流三種實現思路總結