4

我有一个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];
}

我觉得我一定错过了一些明显的东西,但这让我很难过。

4

2 回答 2

9

动画故障出现在contentSize集合视图缩小的地方,以至于它的高度或宽度变得小于(或等于)集合视图边界的高度或宽度。

可以使用setContentOffset:animated:和类似的方法强制批量更新块中的预期动画,但这依赖于知道删除后的投影内容大小。内容大小由集合视图布局管理,但由于我们还没有真正删除单元格,我们不能只询问布局(或者我们会得到旧大小)。

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

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

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

于 2014-01-07T10:50:52.333 回答
0

这对我很有效,引用自问题讨论

[self.dataArray removeObjectAtIndex:index];
[self.collectionView deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:index inSection:0]]];
[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadData];
} completion:nil];
于 2018-04-27T05:50:28.143 回答