Reputation: 1831
The animation by itself works when I use a constraint on the distance between the UIImageView and the top of the parent UIView without vertical and horizontal centering.
The constraints on the UIImageView:
The animation works great when I use this:
self.logoImageViewVerticalSpaceConstraint.constant = 20;
[UIView animateWithDuration: 1.0
delay: 0
options:(UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction)
animations:^{[self.logoImageView layoutIfNeeded];}
completion:^(BOOL finished) {NSLog(@"Finished animation"); }];
The issue kicks in when I don't want to use a static space to top layout constraint because the imageview needs to be centred for 3.5 and 4 inch devices. To solve this I thought starting off with a vertical and horizontal center constraint.
Now I thought I could simply remove the y center constraint and adding the space to top layout constraint of 20pt myself:
[self.logoImageView removeConstraint:self.logoImageViewYCenterConstraint];
NSLayoutConstraint *topSpaceConstraint = [NSLayoutConstraint
constraintWithItem:self.view attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual toItem:self.logoImageView
attribute:NSLayoutAttributeTop multiplier:1
constant:20];
[self.view addConstraint:topSpaceConstraint];
[UIView animateWithDuration: 1.0
delay: 0
options:(UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction)
animations:^{
[self.logoImageView layoutIfNeeded];
}
completion:^(BOOL finished) {
NSLog(@"Finished animate");
}];
The result is that the UIImageView stays centred and it blows up a bit. Which is the total opposite of what I expect to happen because I removed the x center constraint. Added the top constraint with distance 20pt to the top of the parent UIView and I did not touch any other constraints (like the width and height).
Upvotes: 2
Views: 1342
Reputation: 385590
An NSLayoutConstraint
has one or two views that it constrains. In your case, the views are self.logoImageView
and self.view
.
To have any effect, the constraint must be installed on a view, and not just any view. The constraint must be installed on a common ancestor of both constrained views. (Note that a view is considered to be an ancestor of itself.) And when you remove a constraint, you must remove it from the view on which it is installed.
You're trying to remove the centering constraint from self.logoImageView
, but the constraint can't have been installed on that view.
As of iOS 8.0, the preferred (and easiest) way to uninstall a constraint is to set its active
property to NO
:
self.logoImageViewYCenterConstraint.active = NO;
Prior to iOS 8.0, you have to remove it from the view where it's installed. The constraint is probably installed on self.view
. So try this instead:
[self.view removeConstraint:self.logoImageViewYCenterConstraint];
Note also that if you want to animate the image view back to the center, you'll need to uninstall topSpaceConstraint
and reinstall self.logoImageViewYCenterConstraint
.
A different way to handle this is to install both constraints simultaneously, but give one of them a lower priority. When you need to change the position of the image view, change the priorities of the constraints. Thus:
- (void)viewDidLoad {
[super viewDidLoad];
if (self.topSpaceConstraint == nil) {
self.topSpaceConstraint = [NSLayoutConstraint constraintWithItem:...];
self.topSpaceConstraint.priority = 1;
[self.view addConstraint:self.topSpaceConstraint];
}
}
- (void)setImageViewCenteredVertically:(BOOL)isCentered animated:(BOOL)animated {
if (isCentered) {
self.topSpaceConstraint.priority = 1;
self.logoImageViewYCenterConstraint.priority = UILayoutPriorityRequired;
} else {
self.topSpaceConstraint.priority = UILayoutPriorityRequired;
self.logoImageViewYCenterConstraint.priority = 1;
}
if (animated) {
[UIView animateWithDuration:1 delay:0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
[self.view layoutIfNeeded];
}
completion:nil];
}
}
Upvotes: 1
Reputation: 1927
I'm not really a master of NSLayoutConstraints
, but either you should add the constraint to the logoImageView
object or you should change the constraintWithItem:
parameter because to me something looks strange right now. You're removing a constraint from the imageView, then adding a constraint to the self.view
object which refers to self.view
item
Upvotes: 0