2

当我对 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"); }];

当我不想使用静态空间来顶部布局约束时,问题就会出现,因为图像视图需要居中以用于 3.5 和 4 英寸设备。为了解决这个问题,我想从垂直和水平中心约束开始。

  • 宽度:240
  • 身高:128
  • 将中心 x 对齐到:superview --> 连接到 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 中心约束。将距离为 20pt 的顶部约束添加到父 UIView 的顶部,我没有触及任何其他约束(如宽度和高度)。

4

2 回答 2

1

AnNSLayoutConstraint有一个或两个受其约束的视图。在您的情况下,视图是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];
    }
}
于 2013-08-07T21:04:26.440 回答
0

我不是真正的大师NSLayoutConstraints,但要么你应该将约束添加到logoImageView对象,要么你应该更改constraintWithItem:参数,因为对我来说现在有些东西看起来很奇怪。您正在从 imageView 中删除约束,然后向self.view引用self.viewitem的对象添加约束

于 2013-08-07T21:03:25.560 回答