Search code examples
iosobjective-cuiviewnslayoutconstraint

Constraints animation is incorrect


I created uiview custom class and implemented in Main View Controller

-(KPHomeChartCategory *)chartCategory {

    if (!_chartCategory) {
    _chartCategory = [[KPHomeChartCategory alloc] init];
    _chartCategory.delegate = self;
    _chartCategory.translatesAutoresizingMaskIntoConstraints = NO;
    [self addSubview:_chartCategory];

    [self.chartCategory.topAnchor constraintEqualToAnchor:self.topAnchor constant:-7.5].active = YES;
    [self.chartCategory.rightAnchor constraintEqualToAnchor:self.rightAnchor].active = YES;

    self.chartCategoryLeftAnchor = [self.chartCategory.leftAnchor constraintEqualToAnchor:self.rightAnchor];
    self.chartCategoryLeftAnchor.active = YES;

    [self.chartCategory.heightAnchor constraintEqualToConstant:100].active = YES;

    }
    return _chartCategory;
}

I animated uiview custom class (KPHomeChartCategory) constraints in this way

-(void)openPanelTagAnimation {

    self.chartCategoryLeftAnchor.active = NO;
    self.chartCategoryLeftAnchor = [self.chartCategory.leftAnchor constraintEqualToAnchor:self.rightAnchor constant:-self.frame.size.width +105];
    self.chartCategoryLeftAnchor.active = YES;

    [UIView animateWithDuration:.6 delay:0 usingSpringWithDamping:1 initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseOut animations:^{
        self.customSwitch.alpha = 0;
        [self layoutIfNeeded];
    } completion:nil];
}

Now if you look at the video, you will notice that the first time I show customView, my collection view is shown from above but afterwards the animation seems to be perfectly straightforward ... can you make me understand why this thing?

Video Link
VIDEO ANIMATION

Why my animation first starts from top to bottom and only then is linear ? (the linear animation from right to left is the correct one and should be the first time the custom view is animated)


Solution

  • In the animation you posted the cells are animating because their initial size is CGSizeZero or some value close to that and then the collection view layout invalidates so their size is increased. You could avoid this by animating the transform property of your collection view. This will like solve the problem you mention here as well. For example in a simple demo, I can place a collection view by pinning top, left and right to its superview with a constant height. I set the cell sizes programmatically like:

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
        return CGSizeMake(collectionView.bounds.size.width / 3.0, collectionView.bounds.size.height);
    } 
    

    Then I use a CGAffineTransform to move the collection view off screen. For example:

    - (void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
        self.collectionView.transform = CGAffineTransformTranslate(CGAffineTransformIdentity, self.view.bounds.size.width, 0.0);
    }
    

    Finally, when I want to perform an animation, I set the transform back to its identity:

    - (void)animate {
        // Reversing and repeating for the sake of testing
        [UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
            self.collectionView.transform = CGAffineTransformIdentity;
        } completion:nil];
    }
    

    Using this method ensures that cells are always the same size and thus won't animate when constraints change in an animation block.

    When I change constraints in my demo project this is the animation, notice the cell sizes change on the initial animation.

    enter image description here

    The same animation when setting transform:

    enter image description here