UICollectionView moveItemAtIndexPath:toIndexPath: 问题移动项目不在屏幕上

Posted

技术标签:

【中文标题】UICollectionView moveItemAtIndexPath:toIndexPath: 问题移动项目不在屏幕上【英文标题】:UICollectionView moveItemAtIndexPath:toIndexPath: issues moving items not on screen 【发布时间】:2012-12-04 07:49:35 【问题描述】:

我正在尝试在 ios 6 上的 UICollectionView 中为重新排序的项目设置动画。

我写了这段代码:

    NSMutableDictionary *from = [NSMutableDictionary dictionaryWithCapacity:self.count];
    for (int ii = 0; ii < self.count; ii++) 
        MyItem item = [self getItemAtIndex:(NSInteger)ii];
        [from setObject:[NSNumber numberWithInt:ii] forKey:[NSNumber numberWithInt:item.id]];
    

    [self sort];

    [self.collectionView performBatchUpdates:^
        for (int ii = 0; ii < self.count; ii++) 
            MyItem item = [self getItemAtIndex:(NSInteger)ii];
            NSNumber *prevPos = (NSNumber *)[from objectForKey:[NSNumber numberWithInt:item.id]];
            if ([prevPos intValue] != ii) 
                NSIndexPath *from = [NSIndexPath indexPathForItem:prevPos.intValue inSection:0];
                NSIndexPath *to = [NSIndexPath indexPathForItem:ii inSection:0];
                [self.collectionView moveItemAtIndexPath:from toIndexPath:to];
            
        
     completion:nil];

首先,我将项目的所有当前位置保存在字典中,然后将项目排序到新位置,然后检查所有项目,并将它们从旧位置移动到新的。

当所有项目都显示在屏幕上时,这很有效,但如果列表长于 10,这会使某些项目当前不可见(因为它们位于列表的可见部分之上或之下),则会导致这些项目突然出现在可见索引中并在其他地方设置动画,当动画停止时它们被隐藏。 这看起来真的很奇怪,因为有些项目出现在其他项目之上......

这是 iOS 6 UICollectionView 的问题吗,我在这里做错了吗?

【问题讨论】:

【参考方案1】:

看起来UICollectionView 正在重用单元格,从而使您的动画看起来很糟糕。任何离开屏幕的单元格都可以重复使用。

那么为什么你的动画看起来很时髦?

当您移动单元格时,单元格的开始和结束位置以及它是否被隐藏都会自动处理。为了让这些动画看起来不错,您还需要更新数据源,因为代码似乎使用它来确定动画期间单元格的开始和结束位置。

在调用索引更新块之前,请确保您的数据源已使用新的索引位置进行更新。这样一来,Apple 的代码就拥有了以更美观的方式移动您的单元格所需的信息。

来自Apple documentation on UICollectionViews:

要插入、删除或移动单个部分或项目,您必须按照以下步骤操作:

    更新数据源对象中的数据。 调用集合视图的适当方法来插入或删除部分或项目。

在通知集合视图任何更改之前更新数据源至关重要。集合视图方法假定您的数据源包含当前正确的数据。如果没有,collection view 可能会从您的数据源接收到错误的项目集,或者请求不存在的项目并导致您的应用崩溃。

【讨论】:

嘿@redlightbulb,感谢您的回复,电话[自我排序];将数据源更新到新位置。所以,我认为可重复使用的单元格妨碍动画是对的,但我想不出一个好的解决方案。你能推荐一个固定的代码吗? 嗨@mar​​mor - 你使用什么布局?在插入单元格时控制单元格开始位置的方法是 initialLayoutAttributesForInsertedItemAtIndexPath。如果您在其中放置逻辑以将您的单元格放置在当前可见区域的上方或下方,它应该允许您从屏幕外看到您的单元格“飞入”。让我知道这是否有帮助! (链接:developer.apple.com/library/ios/#documentation/uikit/reference/…) 我在 Grid 布局中使用 UICollectionView,这是一个很好的提示,我会检查一下...

以上是关于UICollectionView moveItemAtIndexPath:toIndexPath: 问题移动项目不在屏幕上的主要内容,如果未能解决你的问题,请参考以下文章

记一次思维转变的时刻

在一个 catch 块中处理多个 swift 错误

折叠UICollectionView

-[UICollectionView _endItemAnimations] 中的 UICollectionView 断言失败

如何滚动另一个 UICollectionView 下方的 UICollectionView?

UICollectionView 单元内部已加载,但 UICollectionView 未显示