iOS Collection View 編程指導(三)-如何使用Flow Layout

UICollectionViewFlowLayout類來管理collectionView中的布局, 它是一個具體的類, 可以直接使用. flow layout實現(xiàn)了一種基于線性的斷裂式布局, 也就是說collectionView中的item是按照線性順序排列的, 該布局會盡量適配item的間距, 使得item排列在同一行, 如果超出一行會接著進行下一行的排列. 圖3-1展示了水平方向上的flow layout.

圖3-1 使用flow layout布局section和cell

使用flow layout除了可以實現(xiàn)一個網(wǎng)格狀的collectionView, 還可以實現(xiàn)更多樣式. 比如, 你可以調(diào)整間距來實現(xiàn)一個單行滾動的collectionView. 如果item的size可以不同, 這樣可以產(chǎn)生非對稱效果. 你可以通過代碼和xib來配置你的flow layout對象, 步驟如下:

  • 創(chuàng)建一個flow layout對象, 將其賦值給collectionView
  • 設置cell的width和height
  • 設置行間距, item的間距
  • 如果你想要section header和footer, 給footer和header設置size
  • 設置flow layout滾動的方向(scroll layout)

注意:配置layout時, 你至少需要配置cell的寬高, 不然item默認的寬高為0, 導致item不可見

自定義Flow Layout Attributes


flow layout對象暴露了幾個屬性用于配置item的外觀, 當你設置這些屬性時, 該屬性對所有的item都有起作用. 比如你通過屬性itemSize來配置item的大小后, 所有的item大小都和屬性中配置的一樣.

如果你想item的size和spacing都不一樣, 那么你需要實現(xiàn)flow layout的委托UICollectionViewDelegateFlowLayout. 你可以將collectionView的delegate和flow layout的delegate設置成同一個. 當flow layout的delegate實現(xiàn)了相應的方法后, layout對象根據(jù)你實現(xiàn)的方法中返回的值來設置item的size和spacing.

設置item的size

  • 如果collectionView中的cell大小相同, 那么flow layout中的item的size大小可以通過itemSize來確定.
  • 如果item的size要不同, 那么需要實現(xiàn)委托方法collectionView:layout:sizeForItemAtIndexPath:來確定不同item的size. 在委托方法中, 你可以根據(jù)index path來確定不同item, 從而確定特定item的size. 如圖3-2展示了不同item的不同size
圖3-2 flow layout中的不同itemSize

注意:如果item的size是不同的, 那么會導致不同行的item的數(shù)量不同

設置行間距和itme的間距

  • 使用flow layout布局時, 你可以設置item間的最小間距, 以及最小行間距. 需要注意, 是最小間距, 而不是具體的間距, 也就是說實際顯示的間距可能和你設置最小間距不同, 有可能大于最小間距.
  • 在布局時, flow layout往一行中加item, 直到一行顯示不下, 才開始第二行. 如果一行剛好可以顯示整數(shù)個item沒有額外的空間, 那么此時item的間距為最小間距. 若果還有額外的空間, 那么layout對象會將item的間距均勻地調(diào)大以剛好適配屏幕. 如圖3-3所展示調(diào)整itme的間距來避免最后留下大塊空間
圖3-3 item的實際間距大于最小間距
  • 對于行間距, flow layout使用同樣原理來管理. 而且當item的size不同時, 導致行間距也不同. 行間距的實際距離和相鄰兩行中最大的兩個item有關, 如圖3-4所示


    圖3-4 不同itemSize時的行間距
  • flow layout提供兩個屬性minimumLineSpacingminimumInterItemSpacing來設置靜態(tài)的行間距和item間距, 如果想動態(tài)提供行間距和item間距可以使用委托方法collectionView:layout:minimumLineSpacingForSectionAtIndex:collectionView:layout:minimumInteritemSpacingForSectionAtIndex:來提供動態(tài)的間距.

使用Section Insets來調(diào)節(jié)section的margin

section inset是調(diào)節(jié)cells使用空間的一種手段. 你可以在section的左右, header/footer上下之間插入間距達到調(diào)節(jié)cell布局的空間大小. 如圖3-5所示, 展示section inset的作用.


圖3-5 section inset調(diào)節(jié)cell的可用空間

什么時候使用子類化的Flow Layout


在有的情況下, 使用UICollectionViewFlowLayout滿足不了需求, 需要繼承UICollectionViewFlowLayout做一些定制化的操作才行. 下面列舉了使用子類化UICollectionViewFlowLayout的幾種情況:

  • 給你的布局添加新的補充視圖(supplementary)和裝飾視圖(decoration)

    標準的flow layout只提供了header, footer沒有decoration view, 為了支持更多的supplementary和decoration view你需要重寫下面的一些方法:

    • layoutAttributesForElementsInRect:(required)
    • layoutAttributesForItemAtIndexPath:(required)
    • layoutAttributesForSupplementaryViewOfKind:atIndexPath:(為了支持新的supplementary視圖)
    • layoutAttributesForDecorationViewOfKind:atIndexPath:(為了支持新的decoration視圖)
      layoutAttributesForElementsInRect:方法中, 需要調(diào)用父類方法來獲得cell的layout attribute對象, 然后再添加supplementary或者decoration的layout attribute對象. 再使用其他方法來提供其他attribute. 關于如何創(chuàng)建layout attribute請看Creating Layout Attributes
  • 給flow layout返回的layout attribute對象做點調(diào)整

    重寫layoutAttributesForElementsInRect:方法以及其他返回layout attribute對象的方法. 在這些方法中你應該調(diào)用super來獲取attribute對象, 在方法中修改調(diào)用super獲取layout attribute對象, 然后返回.

  • 給cell和其他view替換新的layout attribute對象

    • 通過集成UICollectionViewLayoutAttributes類, 自定義layout attribute對象, 你可以往layout attribute中添加新的特性(屬性).
    • 然后在UICollectionViewFlowLayout的子類重寫layoutAttributesClass方法返回你自定義的UICollectionViewLayoutAttributes的子類.
    • 你還應該重寫layoutAttributesForElementsInRect:,layoutAttributesForItemAtIndexPath:方法, 在這些方法中你要給新的layout attribute對象中屬性賦值.
  • 插入/刪除的item, 確定item的initial/final位置

    默認情況下, 當你插入/刪除cell時, 只有一個fade動畫, 如果你想要自定義動畫, 可以重寫下面的方法:

    • initialLayoutAttributesForAppearingItemAtIndexPath:
    • initialLayoutAttributesForAppearingSupplementaryElementOfKind:atIndexPath:
    • initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath:
    • finalLayoutAttributesForDisappearingItemAtIndexPath:
    • finalLayoutAttributesForDisappearingSupplementaryElementOfKind:atIndexPath:
    • finalLayoutAttributesForDisappearingDecorationElementOfKind:atIndexPath:
      在cell被插入/刪除前, 你可以通過上面的方法來設置特定的layout attribute對象, 然后flow layout會使用這些attribute來進行動畫. 如果你重寫了這些方法, Apple推薦你也重寫prepareForCollectionViewUpdates:finalizeCollectionViewUpdates這兩個方法. 你可以使用者兩個方法來跟蹤當前周期內(nèi)那個item被插入/刪除. 想知道關于刪除/插入的工作原理, 請看Making Insertion and Deletion Animations More Interesting

上面的幾種情況和操作也適用于創(chuàng)建自定義的layout, 不過在自定義layout之前考慮一下是否可以使用子類化的flow layout, 如果可以的話, 建議優(yōu)先使用flow layout的子類, 因為flow layout是經(jīng)過蘋果精心設計的, 效果更好. 事實上, 需要用到自定義layout的情況很少, 因為使用flow layout或繼承flow layout可以滿足大多數(shù)需求. 只有少數(shù)情況下才需要自定義layout, 比如, 你的布局不是基于線性的, 或者你的內(nèi)容不局限在屏幕兩個方向上滾動, 你布局中的item經(jīng)常移動, 在這些情況下用自定義layout更好點.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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