2016-04-27 53 views
3

我有一個數據集被分成多個部分,但是,我想顯示這在一個collectionView中沒有中斷節之間。這裏是什麼,我想實現一個例證:UICollectionView刪除分節符與UICollectionViewFlowLayout

Instead of: 
0-0 0-1 0-2 
0-3 
1-0 1-1 
2-0 
3-0 

I want: 
0-0 0-1 0-2 
0-3 1-0 1-1 
2-0 3-0 

我實現的解決方案可能在於自定義UICollectionViewLayout子類,但我不知道如何實現這樣的事情。

感謝

+0

只使用一個部分將產生所需的結果。你有什麼理由需要使用多個部分? – bsmith11

+0

我正在使用一個NSFetchedResultsController,它有一個定義的sectionNameKeyPath,將結果分解成這些部分。此控制器和緩存的結果在此collectionView和另一個顯示分節符的tableView之間共享 - 因此需要設置sectionNameKeyPath。我意識到我可以做一些時髦的NSIndexPath切換,使其在一個部分爲collectionView工作,但我認爲最乾淨的解決方案是調整流佈局。 –

+0

我不相信有一個乾淨的方式來實現你想要的,而不需要繼承'UICollectionViewLayout'。如果你使用了兩個單獨的NSFetchedResultsController呢? – bsmith11

回答

0

你是正確的,你需要繼承UICollectionViewLayout。 開始之前需要了解的基本知識是,您需要至少計算集合視圖中每個單元格的位置和大小。 UICollectionViewLayout只是提供該信息的結構化方式。你得到結構,但你必須自己提供一切。

有4種方法,你需要重寫:

  • 準備
  • 的invalidateLayout
  • layoutAttributesForItemAtIndexPath
  • layoutAttributesForElementsInRect

一個竅門是緩存中查找表的佈局屬性(字典):

var cachedItemAttributes = [IndexPath: UICollectionViewLayoutAttributes]() 

準備,你計算你的CollectionView每個indexPath佈局屬性:

override func prepare() { 
    super.prepare() 
    calculateAttributes() 
} 

的invalidateLayout重置緩存佈局屬性,並重新計算它們:

override func invalidateLayout() { 
    super.invalidateLayout() 
    cachedItemAttributes = [:] 
    calculateAttributes() 
} 

layoutAttributesForItemAtIndexPath您使用查找表返回正確的佈局屬性:

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 
    return cachedItemAttributes[indexPath] 
} 

layoutAttributesForElementsInRect您篩選的查找表指定的矩形內的元素:

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 
    return cachedItemAttributes.filter { rect.intersects($0.value.frame) }.map { $0.value } 
} 

的最後一塊拼圖是實際計算佈局屬性。在這裏,我將只提供僞代碼:

func calculateAttributes() { 
    // For each indexpath (you can get this from the collectionView property using numberOfSections and numberOfItems:inSection) 
    // calculate the frame, i.e the origin point and size of each cell in your collectionView and set it with UICollectionViewLayoutAttributes.frame 
    // There are many other properties on UICollectionViewLayoutAttributes that you can tweak for your layout, but frame is a good starting point from which you can start experimenting. 
    // Add the layout attributes to the lookup table 
    // end loop 
} 

要回答你的問題,這裏是僞代碼來計算每個單元的位置:

// If width of cell + current width of row + spacing, insets and margins exceeds the available width 
// move to next row. 
// else 
// cell origin.x = current width of row + interitem spacing 
// cell origin.y = number of rows * (row height + spacing) 
// endif 

如果您需要您的自定義佈局可配置,那麼如果可用的簽名足夠,則使用UICollectionViewDelegateFlowLayout;或者定義從UICollectionViewDelegateFlowLayout或UICollectionViewDelegate繼承的自己。因爲你的協議是從UICollectionViewDelegateFlowLayout繼承而來的,UICollectionViewDelegateFlowLayout本身是從UICollectionViewDelegate繼承的,所以你可以直接在你的viewcontroller中將它設置爲collectionView委託。在您的自定義集合視圖佈局中,您只需將來自UICollectionViewDelegate的委託轉換爲您的自定義協議即可使用它。請記住處理投射失敗或協議方法未由代表實施的情況。