2012-11-21 50 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? 
相关问题