ios - 在 deleteItemsAtIndexPaths 上的 UICollectionView 中动画 contentOffset 变化

标签 ios objective-c uicollectionview contentsize contentoffset

我有一个 UICollectionView,可以在其中添加和删除单元格。我正在使用 performBatchUpdates 进行这些更改,并且布局按预期进行动画处理。

当我滚动到内容的末尾并删除一个项目使得 contentSize 减小时,问题就来了:这导致 contentOffset 发生变化,但变化是'动画。相反,contentOffset 在删除动画完成后立即跳转。我尝试在删除的同时手动更新 contentOffset 但这对我也不起作用。

我使用的是自定义布局,但我使用以下代码看到了与标准流布局相同的行为:

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.items.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    UILabel *label = (UILabel *)[cell viewWithTag:1];
    label.text = [self.items objectAtIndex:indexPath.item];
    return cell;
}

- (IBAction)addItem:(UIBarButtonItem *)sender
{
    self.runningCount++;
    [self.items addObject:[NSString stringWithFormat:@"Item %u",self.runningCount]];
    [self.collectionView performBatchUpdates:^{
        [self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:self.items.count-1 inSection:0]]];
    } completion:nil];
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    [self.items removeObjectAtIndex:indexPath.item];

    [self.collectionView performBatchUpdates:^{
        [self.collectionView deleteItemsAtIndexPaths:@[indexPath]];
    } completion:nil];
}

我觉得我一定遗漏了一些明显的东西,但这让我很困惑。

最佳答案

在 Collection View 的 contentSize 缩小时可以看到动画故障,使其高度或宽度小于(或等于) Collection View 边界的高度或宽度。

可以使用 setContentOffset:animated: 和类似方法在批量更新 block 中强制执行预期的动画,但这依赖于了解删除后的预计内容大小。内容大小由 Collection View 布局管理,但由于我们还没有真正删除单元格,我们不能只询问布局(否则我们会得到旧大小)。

为了解决这个问题,我在我的自定义布局中实现了 targetContentOffsetForProposedContentOffset: 方法来根据需要调整内容偏移量。下面的代码仅考虑了 Y 偏移量,足以满足我的需求:

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset
{
    if (self.collectionViewContentSize.height <= self.collectionView.bounds.size.height)
    {
        return CGPointMake(proposedContentOffset.x,0);
    }
    return proposedContentOffset;
}

我在一个直接的 UICollectionViewFlowLayout 子类中尝试了这个,它也在那里完成了工作。

关于ios - 在 deleteItemsAtIndexPaths 上的 UICollectionView 中动画 contentOffset 变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20948356/

相关文章:

ios - (iOS) 如何让 UIPickerView 中的第一个值不可选?

iphone - 混合不同大小的声音文件

objective-c - NSManagedObject 不反射(reflect)后台线程 NSManagedObjectContextDidSaveNotification 后的更改

iphone - 如何删除“"icon dimensions (0 x 0) don' t满足大小要求”的警告?

ios - 如何设置自定义collectionView Cell Frame?

ios - UICollectionView可以横向计数吗?

ios - 字符串中的多个错误

cocoa-touch - 是否有适用于 iOS 的数据绑定(bind)机制?

ios - 核心数据不持久保存对象

ios - UI Collection View 单元格和自动布局