如何在更改集合视图单元格大小时为其内部视图添加动画效果?

9
我有一个集合视图,我想要的效果是当单元格被点击时,它会增长到占据整个屏幕。为了实现这一点,我基本上只需要在didSelectItemAtIndexPath中调用performBatchUpdates,而sizeForItemAtIndexPath则知道对于选定的单元格返回更大的大小。这一切都很好地运作,单元格可以按预期增长和缩小。
问题出在单元格内部。集合视图单元格由一组受约束管理的中等复杂视图层次结构组成。我希望单元格的子视图随着动画单元格的增长和缩小而增长和缩小。不幸的是,我的子视图在单元格缓慢动画到其新大小时立即捕捉到其新位置。如何确保单元格内容与单元格大小一起动画?
以下是集合视图控制器中的两个相关方法:
- (CGSize) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
if ([collectionView.indexPathsForSelectedItems containsObject:indexPath])
    return CGSizeMake(collectionView.bounds.size.width - 20, collectionView.bounds.size.height - (20 + [self.topLayoutGuide length]));
else
    return CGSizeMake(260, 100); 
}

- (void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    [collectionView performBatchUpdates:nil completion:nil];
}

1
你的子视图很可能会自动对齐,因为某个标志表示单元格正在展开,从false变为true,然后调用layoutSubviews,立即将子视图移动到它们的展开位置。我只是猜测 - 如果您添加代码,我们将能够看到是否是这种情况。另外一点 - 单元格是否应该在集合中覆盖其他单元格,还是应该将它们推出去?如果应该在顶部展开,我建议在UICollectionView上方添加一个新视图并进行动画处理。 - Ian
我添加了两个相关的方法,用于在选择时进行调整大小。视图控制器中几乎没有其他代码。单元格本身是一些nib文件,无法轻易地添加到帖子中。 - Mike
3个回答

11

我曾经遇到了完全相同的问题。经过尝试,以下代码为我解决了这个问题。在批量更新后直接调用layoutIfNeeded,并带有3.0秒的持续时间(+-批量更新持续时间),可以动画地应用约束。

[self performBatchUpdates:nil completion:nil];

// IndexPath of cell to be expanded
UICollectionViewCell *cell = [self cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:0.3 animations:^{
    [cell.contentView layoutIfNeeded];
}];

谢谢你,你救了我免于在这里发疯。 - logancautrell
是的,这个方法可行,我用它解决了同样的问题。 - Sherlock

2
我想进一步解释Antoine的回答。在动画块内调用performBatchUpdates:completion:实际上会设置单元格调整大小的持续时间,并将内容调整大小匹配到它上面。
[UIView animateWithDuration:0.3 animations:^{
    [self performBatchUpdates:^{
        // set flags needed for new cell size calculation
    } completion:nil];
    [collectionView layoutIfNeeded];
}];

这样你还可以自由调整动画的时间,甚至使用弹簧动画。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接