Animating Constraint Changes, position animates but height jumps without animation

ios, ios7, nslayoutconstraint

Solution

I don't think you're doing anything wrong, this seems to be the way that labels behave when you try to animate their height. I know I've wrestled with this problem in the past, and I can't remember if I've ever found a solution that works by animating the constraints in an animation block. The way I have gotten it to work is to use a timer or CADisplayLink to adjust the height constraint.

-(void)shrinkLabel {
    self.constraintWhiteHeight.constant -= 1;
    if (self.constraintWhiteHeight.constant >= secondaryHeight)
    [self performSelector:@selector(shrinkLabel) withObject:nil afterDelay:.05];
}

After Edit:

Although the timer method works, it doesn't always look smooth, depending on the speed and increments you use. Another way to do this is to use a large UIView (the same size as the yellow label in your movie) with a smaller UILabel inside that has centerX and centerY constraints to the larger view. Then, animate the yellow view as usual with animateWithDuration:animations:

-(void)shrinkLabel {
    self.yellowViewHeightCon.constant = secondaryHeight;
    [UIView animateWithDuration:5 animations:^{
        [self layoutIfNeeded];
    }];
}

Problem

I have a custom UIView. Within that UIView I have a UILabel with a yellow background containing @"8" called `labelWhite`. I programmatically create 4 constraints for that UILabel: top, left, width, and height. When I tap the UIView, I change the constant value of the height and animate the layout over 5 seconds. However, the height of the view immediately jumps to the new value, but the y position also changes and jumps to a new value immediately. Then over the 5 second animation, the y position animates back to where it should have stayed all along. You can see a video of it happening here: http://inadaydevelopment.com/stackoverflow/Constraints0.mov What it SHOULD do is just remain at y=0 and shrink vertically. What am I doing wrong? EDIT: I just discovered that my animations work exactly as intended if my subviews are UIViews, but as UILabels I get the jump-size + animate-position. What is going on? Is there a way I can get UILabels to animate their size? This is the code I use to modify and animate the layout: ``` self.constraintWhiteHeight.constant = secondaryHeight; [UIView animateWithDuration:5.0 animations:^{ [self layoutIfNeeded]; }]; ``` This is the code I use to create the constraints: ``` // ------ Top ----- NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.labelWhite attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; [self addConstraint:constraint]; // ------ Left ----- self.constraintWhiteLeft = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.labelWhite attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0]; // ------ Width ----- NSString *constraintString = [NSString stringWithFormat:@"H:[_labelWhite(==%.0f)]", self.bounds.size.width]; NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:constraintString options:0 metrics:nil views:NSDictionaryOfVariableBindings(_labelWhite)]; NSLog(@"constraints: %@", constraints); self.constraintWhiteWidth = [constraints objectAtIndex:0]; [self.labelWhite addConstraints:constraints]; // ------ Height ----- constraintString = [NSString stringWithFormat:@"V:[_labelWhite(==%.0f)]", primaryHeight]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:constraintString options:0 metrics:nil views:NSDictionaryOfVariableBindings(_labelWhite)]; self.constraintWhiteHeight = [constraints objectAtIndex:0]; [self.labelWhite addConstraints:constraints]; ```

Original source