Search code examples
objective-cuikit

Missing animation on constraint change using UIKit and Objective-C


I have a parent UIView called ProgressBarView. Inside, I've setup a UIView called progressForeground that is responsible for showing the actual percentage of the progress bar. I want progressForeground to animate to its set width constraint. This is how I setup the view:

UIView *progressForeground = [[UIView alloc] init];
        
[self addSubview:progressForeground];
    
progressForeground.translatesAutoresizingMaskIntoConstraints = NO;
[progressForeground.heightAnchor constraintEqualToConstant:frame.size.height].active = YES;
progressForeground.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1.0];
[progressForeground.leadingAnchor constraintEqualToAnchor:progressBackground.leadingAnchor].active = YES;
[progressForeground.centerYAnchor constraintEqualToAnchor:progressBackground.centerYAnchor].active = YES;
progressForeground.layer.cornerRadius = 5;

After I've setup the neccessary constraint, I've added a width constraint and changed its value inside an animation block like so:

NSLayoutConstraint *progressForegroundWidthConstraint = [NSLayoutConstraint constraintWithItem:progressForeground
            attribute:NSLayoutAttributeWidth
            relatedBy:NSLayoutRelationEqual
            toItem:nil
            attribute:NSLayoutAttributeNotAnAttribute
            multiplier:1.0
            constant:0
        ];
        
progressForegroundWidthConstraint.active = YES;
        
[self layoutIfNeeded];
[UIView animateWithDuration:5
     animations:^{
         progressForegroundWidthConstraint.constant = 60;
         [self layoutIfNeeded];
     }
];

As it was mentioned here, I've made sure to call layoutIfNeeded method on the parent view to flush any pending animations.

I expect the width of the progressForegroundView to change with an animation, however it just directly jumps to the value of 60 without any animation. What's wrong here?

I've tried to animate the progressForegroundView, however it only jumped to the designated value without any animation


Solution

  • Fixed it by adding [self setNeedsLayout] after calling [self layoutIfNeeded].

    [self layoutIfNeeded];
    [self setNeedsLayout];
            
    [UIView animateWithDuration:1.5
           animations:^{
                progressForegroundWidthConstraint.constant = progressBarWidth * progressPercentage / 100;
                [self layoutIfNeeded];
           }
    ];