2014-07-07 105 views
4

所以,我試圖用UICollectionView實現一個標籤列表。我正在學習本教程:http://www.cocoanetics.com/2013/08/variable-sized-items-in-uicollectionview/UICollectionView中的項目與流佈局之間的固定間距

問題是UICollectionView中的流佈局嘗試均勻地在同一行上放置項目。

enter image description here

作爲一個開發者,我只能指定minimumInteritemSpacingForSectionAtIndex,這真的到UICollectionView來確定實際的項目間距。

但我真正想實現的是這樣的:

enter image description here

任何想法?

回答

0

Apple爲我們的開發人員提供了UICollectionViewFlowLayout類,它應該足以解決集合視圖的「典型用例」。但是,我相信您的評估中您的默認佈局不允許您創建此標籤雲效果是正確的。如果你需要與普通流佈局不同的東西,你必須編寫你自己的UICollectionViewLayout的子類。

蘋果涵蓋在他們的2012 WWDC會議這個主題名爲「高級收集意見和構建自定義佈局」

一些額外的蘋果文檔:https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/CreatingCustomLayouts/CreatingCustomLayouts.html

在看似偏頗的風險,我也寫了一個快速博客文章貫穿基本步驟:http://bradbambara.wordpress.com/2014/05/24/getting-started-with-custom-uicollectionview-layouts/

希望有所幫助。

3

我已經轉換米洛的解決方案,斯威夫特:https://github.com/Coeur/UICollectionViewLeftAlignedLayout/

它只是子類UICollectionViewFlowLayout

import UIKit 

/** 
* Simple UICollectionViewFlowLayout that aligns the cells to the left rather than justify them 
* 
* Based on https://stackoverflow.com/questions/13017257/how-do-you-determine-spacing-between-cells-in-uicollectionview-flowlayout 
*/ 
open class UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout { 
    open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
     return super.layoutAttributesForElements(in: rect)?.map { $0.representedElementKind == nil ? layoutAttributesForItem(at: $0.indexPath)! : $0 } 
    } 

    open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 
     guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes, 
      let collectionView = self.collectionView else { 
      // should never happen 
      return nil 
     } 

     let sectionInset = evaluatedSectionInsetForSection(at: indexPath.section) 

     guard indexPath.item != 0 else { 
      currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset) 
      return currentItemAttributes 
     } 

     guard let previousFrame = layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame else { 
      // should never happen 
      return nil 
     } 

     // if the current frame, once left aligned to the left and stretched to the full collection view 
     // widht intersects the previous frame then they are on the same line 
     guard previousFrame.intersects(CGRect(x: sectionInset.left, y: currentItemAttributes.frame.origin.y, width: collectionView.frame.width - sectionInset.left - sectionInset.right, height: currentItemAttributes.frame.size.height)) else { 
      // make sure the first item on a line is left aligned 
      currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset) 
      return currentItemAttributes 
     } 

     currentItemAttributes.frame.origin.x = previousFrame.origin.x + previousFrame.size.width + evaluatedMinimumInteritemSpacingForSection(at: indexPath.section) 
     return currentItemAttributes 
    } 

    func evaluatedMinimumInteritemSpacingForSection(at section: NSInteger) -> CGFloat { 
     return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, minimumInteritemSpacingForSectionAt: section) ?? minimumInteritemSpacing 
    } 

    func evaluatedSectionInsetForSection(at index: NSInteger) -> UIEdgeInsets { 
     return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, insetForSectionAt: index) ?? sectionInset 
    } 
} 

extension UICollectionViewLayoutAttributes { 
    func leftAlignFrame(withSectionInset sectionInset: UIEdgeInsets) { 
     frame.origin.x = sectionInset.left 
    } 
}