2012-11-21 78 views
15

有沒有人看到這個問題的正確答案?initialLayoutAttributesForAppearingItemAtIndexPath爲所有可見單元格觸發,而不僅僅是插入的單元格

initialLayoutAttributesForAppearingItemAtIndexPath似乎被稱爲所有可見細胞,而不僅僅是被插入的細胞。根據Apple's own docs

對於移動的項目,集合視圖使用標準方法來檢索項目的更新佈局屬性。對於正在插入或刪除的項目,收集視圖調用一些不同的方法,您應該重寫以提供適當的佈局信息

這聽起來不像發生了什麼......其他細胞不存在插入,他們正在移動,但它的initialLayoutAttributesForAppearingItemAtIndexPath被移動也。

我已經看到使用prepareForCollectionViewUpdates:跟蹤哪些indexPaths正在更新並且只是改變它們,但是這似乎有點奇怪,它會重新發布他們自己的文檔。有沒有人找到更好的解決方法呢?

+0

我唔明這個也是。每次我對集合視圖進行更改時,所有可見單元格都將重新加載,但不清楚如何避免這種情況。當用戶點擊一個區域中的一個單元格時,我重新加載另一個區段,同時在被點擊的單元格中改變動畫。重新加載正在中斷我的動畫,我找不到解決此問題的方法。 – CharlieMezak

回答

9

你並不孤單。 UICollectionViewLayout頭文件註釋使事情變得更清晰。

對於失效前,屏幕上的每一個元素, finalLayoutAttributesForDisappearingXXX將被調用,從屏幕上顯示內容那些最終屬性的 動畫設置。

對於失效後屏幕上的每個元素, initialLayoutAttributesForAppearingXXX將被稱爲動畫 從這些初始屬性到屏幕上結束的設置。

基本上finalLayoutAttributesForDisappearingItemAtIndexPath被稱爲該動畫塊開始之前在屏幕上的每個項目,並且initialLayoutAttributesForAppearingItemAtIndexPath被稱爲爲動畫塊結束後的各項目。您需要緩存在prepareForCollectionViewUpdates中發送的UICollectionViewUpdateItem對象數組,以便知道如何設置初始屬性和最終屬性。在我的情況下,我緩存了以前的佈局矩形prepareLayout,所以我知道要使用的正確初始位置。

有一件事讓我難住了一段時間,你應該使用super的實現initialLayoutAttributesForAppearingItemAtIndexPath並修改它返回的屬性。我只是在執行中調用了layoutAttributesForItemAtIndexPath,並且動畫效果不佳,因爲佈局位置不同。

18

我發現this blog post by Mark Pospesel會有幫助。
作者還修正了WWDC CircleLayout樣本和posted it on Github。感興趣

方法:

- (void)prepareForCollectionViewUpdates:(NSArray *)updateItems 
{ 
    // Keep track of insert and delete index paths 
    [super prepareForCollectionViewUpdates:updateItems]; 

    self.deleteIndexPaths = [NSMutableArray array]; 
    self.insertIndexPaths = [NSMutableArray array]; 

    for (UICollectionViewUpdateItem *update in updateItems) 
    { 
     if (update.updateAction == UICollectionUpdateActionDelete) 
     { 
      [self.deleteIndexPaths addObject:update.indexPathBeforeUpdate]; 
     } 
     else if (update.updateAction == UICollectionUpdateActionInsert) 
     { 
      [self.insertIndexPaths addObject:update.indexPathAfterUpdate]; 
     } 
    } 
} 

- (void)finalizeCollectionViewUpdates 
{ 
    [super finalizeCollectionViewUpdates]; 
    // release the insert and delete index paths 
    self.deleteIndexPaths = nil; 
    self.insertIndexPaths = nil; 
} 

// Note: name of method changed 
// Also this gets called for all visible cells (not just the inserted ones) and 
// even gets called when deleting cells! 
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath 
{ 
    // Must call super 
    UICollectionViewLayoutAttributes *attributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath]; 

    if ([self.insertIndexPaths containsObject:itemIndexPath]) 
    { 
     // only change attributes on inserted cells 
     if (!attributes) 
      attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; 

     // Configure attributes ... 
     attributes.alpha = 0.0; 
     attributes.center = CGPointMake(_center.x, _center.y); 
    } 

    return attributes; 
} 

// Note: name of method changed 
// Also this gets called for all visible cells (not just the deleted ones) and 
// even gets called when inserting cells! 
- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:(NSIndexPath *)itemIndexPath 
{ 
    // So far, calling super hasn't been strictly necessary here, but leaving it in 
    // for good measure 
    UICollectionViewLayoutAttributes *attributes = [super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath]; 

    if ([self.deleteIndexPaths containsObject:itemIndexPath]) 
    { 
     // only change attributes on deleted cells 
     if (!attributes) 
      attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath]; 

     // Configure attributes ... 
     attributes.alpha = 0.0; 
     attributes.center = CGPointMake(_center.x, _center.y); 
     attributes.transform3D = CATransform3DMakeScale(0.1, 0.1, 1.0); 
    } 

    return attributes; 
} 
0

如果你的子類UICollectionViewFlowLayout,您可以撥打super實施。一旦獲得了默認的初始佈局,您可以檢查0.alpha。如果alpha不是0,則單元正在被移動,如果它的0被插入。

我知道這是一個黑客,但它有效。

雨燕2.0的實現如下:

override func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { 


    guard let attributes = super.initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath) where attributes.alpha == 0 else { 
     return nil 
    } 

    // modify attributes for insertion here 

    return attributes 

} 
0

確保您在斯威夫特3.採用新的方法簽名自動更正不適合這種方法的工作:

func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? 
相關問題