当我对UIImageView和父UIView的顶部之间的距离使用约束而没有垂直和水平居中时,动画本身可以工作。
UIImageView上的约束:
使用此动画时效果很好:
self.logoImageViewVerticalSpaceConstraint.constant = 20;
[UIView animateWithDuration: 1.0
delay: 0
options:(UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction)
animations:^{[self.logoImageView layoutIfNeeded];}
completion:^(BOOL finished) {NSLog(@"Finished animation"); }];
当我不想在顶部布局约束中使用静态空间时,这个问题就开始了,因为imageview需要居中放置在3.5英寸和4英寸设备上。为了解决这个问题,我想从垂直和水平中心约束开始。
现在我想我可以简单地删除y中心约束,并自己在20pt的顶部布局约束中添加空间:
[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");
}];
结果是UIImageView保持居中,并且炸毁了一点。
这与我期望的完全相反,因为我删除了x中心约束。在父UIView的顶部添加了距离20pt的顶部约束,而我没有碰到任何其他约束(例如宽度和高度)。
最佳答案
NSLayoutConstraint
具有一个或两个受其约束的视图。在您的情况下,视图为self.logoImageView
和self.view
。
为了产生效果,约束必须安装在一个视图上,而不仅仅是在任何视图上。约束必须安装在上,这是两个受约束视图的共同祖先。 (请注意,视图被认为是其自身的祖先。)并且,当您删除约束时,必须将其从安装了的视图中删除。
您正在尝试从self.logoImageView
删除居中约束,但是该约束尚未安装在该视图上。
从iOS 8.0开始,卸载约束的首选方法(也是最简单的方法)是将其active
属性设置为NO
:
self.logoImageViewYCenterConstraint.active = NO;
在iOS 8.0之前,您必须从安装它的视图中将其删除。该约束可能安装在
self.view
上。因此,请尝试以下操作:[self.view removeConstraint:self.logoImageViewYCenterConstraint];
还要注意,如果要使图像视图重新回到中心,请卸载
topSpaceConstraint
并重新安装self.logoImageViewYCenterConstraint
。处理此问题的另一种方法是同时安装和两个约束,但给其中一个约束设置较低的优先级。当您需要更改图像视图的位置时,请更改约束的优先级。从而:
- (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];
}
}