0

I would like the red button to be animated towards the leading position of the second button :

enter image description here

Some examples showed how to change the "constant" with numbers, but I would like to put automatically at the leading position of the second button.

I tried this, but the red button does not move, the animations log is correctly called though :

- (void)updateConstr{

    NSLayoutConstraint *newLeading = [NSLayoutConstraint
                                                  constraintWithItem:self.redB
                                                  attribute:NSLayoutAttributeLeading
                                                  relatedBy:NSLayoutRelationEqual
                                                  toItem:self.secondButton
                                                  attribute:NSLayoutAttributeLeading
                                                  multiplier:1.0
                                                  constant:0.0f];

    self.leadingConstraint = newLeading;//is an IBOutlet pointing on the constraint (see the image)
    [self.redB setNeedsUpdateConstraints];
    [UIView animateWithDuration:0.5 animations:^{
        [self.redB layoutIfNeeded];
        NSLog(@"animations");//is called, but the red button does not move
    }];
}

- (IBAction)firstAction:(id)sender { //after a click on button "one"
    NSLog(@"firstAction");
    [self updateConstr];
}
Paul
  • 6,108
  • 14
  • 72
  • 128

2 Answers2

1

What I typically do in this situation is the following.

Add two constraints to your scene. One where it's aligned left between the button and the "one" label. The second, where it's aligned left between the button and the "second" label (i.e. both values will be 0). These constraints will initially conflict with one another, and that's fine.

Add IBOutlets to your view controller for the NSLayoutConstraints and assign the two constraints we've created to those IBOutlets.

Set the constraint priority on your initial condition to 999 (i.e. constraint on left align to "one" should be 999). Set the constraint priority on the destination constraint to 998 (i.e. constraint on left align between button to "second" is 998). You'll now see that these constraints will no longer conflict. This is because the priority on one constraint overrides the other.

You may see where this is headed now. So when you want to animate the button between the constraints, swap the priorities and animate!

Code:

@interface MyViewController ()
     @property (nonatomic, weak) NSLayoutConstraint* constraint0;
     @property (nonatomic, weak) NSLayoutConstraint* constraint1;
@end

- (void)someMethodWhereIWantToAnimate
{
     NSInteger temp = constraint0.priority;
     constraint0.priority = constraint1.priority;
     constraint1.priority = temp;

     [UIView animateWithDuration:1.0 animations:^{
         // Simplest is to use the main ViewController's view
         [self.view layoutIfNeeded];
     }];
}
Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
Sandy Chapman
  • 11,133
  • 3
  • 58
  • 67
  • Thanks a lot, how do you add the new constraint, without modifying the first one in the storyboard? With the icons at the bottom, the "new constraints for leading etc." cannot be selected. – Paul Dec 22 '14 at 01:17
  • 1
    Ah, yes, typically when I add constraints, I simply control click and drag between the two elements. So you can control+click on the button and drag to "second" to add a new constraint. Then select the constraint and set it's constant to 0 and set the value to "leading" for both of the elements. @Paul – Sandy Chapman Dec 22 '14 at 13:03
  • Thanks a lot Sandy, I used the small difference with the code from Ganesh, but I keep your solution in mind! Thanks a lot for the answers – Paul Dec 22 '14 at 16:23
  • @Paul Glad you got it working. One nice thing about my solution is that there are no hardcoded values. Everything is modifiable in IB so you don't have to go search for magic numbers in code to update. – Sandy Chapman Dec 22 '14 at 16:27
1

This must do it:

- (void)updateConstr{

    NSLayoutConstraint *newLeading = [NSLayoutConstraint
                                      constraintWithItem:self.redB
                                      attribute:NSLayoutAttributeLeading
                                      relatedBy:NSLayoutRelationEqual
                                      toItem:self.secondButton
                                      attribute:NSLayoutAttributeLeading
                                      multiplier:1.0
                                      constant:0.0f];

    [self.redB.superview removeConstraint: self.leadingConstraint];
    [self.redB.superview addConstraint: newLeading];
    self.leadingConstraint = newLeading;

    [UIView animateWithDuration:0.5 animations:^{
        [self.redB layoutIfNeeded];
    }];
}
Ganesh Kamath
  • 1,181
  • 11
  • 20