Search code examples
iosobjective-cuicollectionviewuicollectionviewcellcalayer

CALayer inside UICollectionViewCell pinch


I added a GIF to describe a problem. I have a UICollectionView with a lot of cells and each cell has a CALayer inside. I have a pinch gesture in my UICollectionView. When it zooming in it looks like each cell zooming apart. See spaces between cells on gif. Is it possible to zoom in each cells together? Thanks in advance Code:

Cell subclass

@property (nonatomic, strong) CALayer *circularLayer;

- (void)layoutSubviews
{
    [self updateRoundedCorners];
}

- (void)updateRoundedCorners
{
    CGRect bounds = self.bounds;
    self.circularLayer.bounds = bounds;
    self.circularLayer.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
}

#pragma mark - Property Set

- (void)setCellObject:(VenueLayoutCellObject *)cellObject
{
    self->_cellObject = cellObject;
    self.objectBackgroundColor = cellObject.objectColor;
    self.type = cellObject.type;
}

Controller

- (void)didReceivePinchGesture:(UIPinchGestureRecognizer *)gesture
{
    static CGFloat scaleStart;

    if (gesture.state == UIGestureRecognizerStateBegan) {
        scaleStart = self.venueLayoutZoom;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged) {
        self.venueLayoutZoom = scaleStart * gesture.scale;
        [self.activeCollectionView.collectionViewLayout invalidateLayout];
    }
}

Updated:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    VenueLayoutCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kVenueLayoutCellReuseIdentifier forIndexPath:indexPath];
    self.activeCollectionViewCellsDictionary[indexPath] = cell;
    if (self.activeCollectionViewObjects.count > indexPath.section) {
        NSArray *rows = self.activeCollectionViewObjects[indexPath.section];
        if (rows.count > indexPath.row) {
            if ([rows[indexPath.row] isKindOfClass:[VenueLayoutCellObject class]]) {
                VenueLayoutCellObject *object = rows[indexPath.row];
                cell.cellObject = object;

            }
        }
    }
    return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout *)collectionViewLayout
  sizeForItemAtIndexPath:(nonnull NSIndexPath *)indexPath
{
    CGFloat widthAndHeight = [self widthAndHeightForActiveCollectionViewItem];
    return CGSizeMake(widthAndHeight *self.venueLayoutZoom, widthAndHeight * self.venueLayoutZoom);
}

- (CGFloat)widthAndHeightForActiveCollectionViewItem
{
    NSArray *array = self.activeCollectionViewObjects;
    __block NSInteger maxCount = 0;
    [array enumerateObjectsUsingBlock:^(NSArray *subArray, NSUInteger idx, BOOL * _Nonnull stop) {
        if (subArray.count > maxCount) {
            maxCount = subArray.count;
        }
    }];
    CGFloat widthAndHeight = CGRectGetWidth(self.activeCollectionView.bounds) / maxCount;
    return widthAndHeight;
}

Solution

  • The changes you are making to the layer are implicitly animated, meaning that they are performed with an animation, even though you haven't specifically told them to.

    Since you're responding to user gestures, you don't want the changes to be animated as this is making them lag behind the gesture.

    You can turn off implicit animations during layoutSubviews like this:

    - (void)layoutSubviews
    {
        [super layoutSubviews];
        [CATransaction begin];
        [CATransaction setDisableActions: YES];
        [self updateRoundedCorners];
        [CATransaction commit];
    }