Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I animate the inner views of a collection view cell while changing it's size?

Tags:

ios

autolayout

I have a collection view, and I'm going for the effect where when a cell is tapped on, it grows to take up the entire screen. To accomplish this, I'm essentially just calling performBatchUpdates inside didSelectItemAtIndexPath, and the sizeForItemAtIndexPath knows to return a larger size for a selected cell. This all works pretty well, the cell grows and shrinks as desired.

The problem is inside of the cell. The collection view cell is made up of a moderately complex view hierarchy managed by constraints. I want the sub views of the cell to grow and shrink with the animating cell. Unfortunately, my subviews are snapping immediately to their new position as the cell slowly animates to it's new size. How can I ensure the content of the cell animates with the cell size?

Here are the two relevant methods from the collection view controller:

- (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];
}
like image 465
Mike Avatar asked Nov 22 '13 03:11

Mike


2 Answers

I had exactly the same problem. After many tries, the following code did the trick for me. Calling layoutIfNeed directly after the batch update with a duration of 3.0 (+- the batchupdate duration) animated the constraints.

[self performBatchUpdates:nil completion:nil];

// IndexPath of cell to be expanded
UICollectionViewCell *cell = [self cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:0.3 animations:^{
    [cell.contentView layoutIfNeeded];
}];
like image 169
Antoine Avatar answered Oct 26 '22 07:10

Antoine


I would like to expand on Antoine's answer. Calling performBatchUpdates:completion: inside the animation block will actually set the cell resize duration and match the content resize to it.

[UIView animateWithDuration:0.3 animations:^{
    [self performBatchUpdates:^{
        // set flags needed for new cell size calculation
    } completion:nil];
    [collectionView layoutIfNeeded];
}];

This way you can also play with the animation timing or even use spring animations.

like image 40
Nikola Lajic Avatar answered Oct 26 '22 05:10

Nikola Lajic