有没有人看到过这个问题的正确答案?
似乎正在为所有可见细胞调用 initialLayoutAttributesForAppearingItemAtIndexPath
,而不仅仅是要插入的细胞。根据{{3}}:
对于移动的项目,集合视图使用标准方法检索项目的更新布局属性。对于要插入或删除的项目,集合视图会调用一些不同的方法,您应该覆盖这些方法以提供适当的布局信息
这听起来不像正在发生的事情......其他单元格没有被插入,它们正被移动,但它正在调用initialLayoutAttributesForAppearingItemAtIndexPath
来移动那些
我已经看到使用prepareForCollectionViewUpdates:
来解决哪些indexPath正在更新并且只更改那些索引路径的工作,但这似乎有点奇怪,它将再次成为他们自己的文档。还有其他人找到了更好的解决方法吗?
答案 0 :(得分:22)
我发现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;
}
答案 1 :(得分:9)
你并不孤单。 UICollectionViewLayout头文件注释使事情更清晰。
对于失效前屏幕上的每个元素, finalLayoutAttributesForDisappearingXXX将被调用并且 动画设置从屏幕上的内容到最终属性。
对于失效后屏幕上的每个元素, initialLayoutAttributesForAppearingXXX将被称为动画 从这些初始属性设置到最终在屏幕上显示的内容。
基本上,在动画块开始之前,屏幕上的每个项目都会调用finalLayoutAttributesForDisappearingItemAtIndexPath
,并且在动画块结束后为每个项目调用initialLayoutAttributesForAppearingItemAtIndexPath
。由您来缓存prepareForCollectionViewUpdates
中发送的UICollectionViewUpdateItem对象数组,以便您知道如何设置初始和最终属性。在我的情况下,我在prepareLayout
中缓存了之前的布局矩形,因此我知道要使用的正确初始位置。
让我困惑一段时间的一件事是你应该使用super的initialLayoutAttributesForAppearingItemAtIndexPath
实现并修改它返回的属性。我刚刚在我的实现中调用了layoutAttributesForItemAtIndexPath
,并且由于布局位置不同,动画无效。
答案 2 :(得分:0)
如果您已经定义了UICollectionViewFlowLayout
,则可以调用super
实施。获得默认初始布局后,您可以检查.alpha
0
。如果alpha
不是0
,则会移动该单元格,如果它正在插入0
。
有点黑客,我知道,但它确实有效。
Swift 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
}
答案 3 :(得分:0)
确保您在Swift 3中使用新方法签名。自动更正不适用于此方法:
func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes?