当我对UIImageView和父UIView的顶部之间的距离使用约束而没有垂直和水平居中时,动画本身可以工作。

UIImageView上的约束:

  • 宽度:240
  • 高度:128
  • 顶部空间到顶部布局:200->连接到logoImageViewVerticalSpaceConstraint

  • 使用此动画时效果很好:
    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英寸设备上。为了解决这个问题,我想从垂直和水平中心约束开始。
  • 宽度:240
  • 高度:128
  • 将中心x对齐到: super 视图->连接到logoImageViewYCenterConstraint
  • 将y中心对齐:superview

  • 现在我想我可以简单地删除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.logoImageViewself.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];
        }
    }
    

    10-05 20:20
    查看更多