iOS:如何为新的自动布局约束(高度)设置动画


123

我以前从未使用过自动布局约束。我正在使用一个小型新应用程序,并且注意到NIB的视图默认为自动布局。因此,我认为我将借此机会与之合作,并尝试弄清苹果公司将如何发展。

第一个挑战:

我需要调整MKMapView的大小,然后将其设置为新位置。如果我以惯常的方式这样做:

[UIView animateWithDuration:1.2f
     animations:^{
         CGRect theFrame = worldView.frame;
         CGRect newFrame = CGRectMake(theFrame.origin.x, theFrame.origin.y, theFrame.size.width, theFrame.size.height - 170);
         worldView.frame = newFrame;
}];

...然后,无论何时更新同级视图(在我的情况下,UISegmentedControl的标题正在更新[myUISegmentedControl setTitle:newTitle forSegmentAtIndex:0]),MKMapView都会“捕捉”回到其原始高度。

所以,我觉得我想要做的是从等于父视图的HIGHT到可相对于UISegmentedControl,它的顶部改变的MKMapView的限制覆盖:V:[MKMapView]-(16)-[UISegmentedControl]

我想要的是缩短MKMapView的高度,以便显示地图视图下的某些控件。为此,我认为我需要将约束从固定的全尺寸视图更改为底部约束到UISegmentedControl顶部的约束...并且我希望它随着视图缩小到新大小而进行动画处理。

如何做到这一点?

编辑- 尽管视图的底部确实会立即向上移动170,但该动画没有设置动画

    [UIView animateWithDuration:1.2f
         animations:^{
             self.nibMapViewConstraint.constant = -170;

    }];

并将其nibMapViewConstraint在IB中连接到底部的垂直空间约束。


1
我知道您可以轻松地在[UIView animateWithDuration ..]块中更改约束的常量值,以对高度变化进行动画处理。您需要为该约束创建一个IBOutlet并将其挂接到xib中,或者如果您在代码中创建了它,则可以保留对其的引用(或遍历所有约束来查找它)。不确定如何为relatedBy更改设置动画,但我已经读到您只应更改常量,而不能更改约束的其他值(对于其他值,请创建一个新约束)。
yuf 2012年

嗯 以为我可以,但我不是在做动画。它改变了成功,并且在动画块,但不是动画!?!
Meltemi 2012年

在这里找到我的答案:< stackoverflow.com/questions/12926566/… >
Meltemi 2012年

1
不要忘了[view layoutIfNeeded],那也是我的问题哈哈。那是解决我的问题的同一问题。
yuf 2012年

可能如何
Sense

Answers:


179

更新约束后:

[UIView animateWithDuration:0.5 animations:^{[self.view layoutIfNeeded];}];

替换self.view为对包含视图的引用。


4
本身适用于视图本身,但是对该视图有约束的视图只是立即移动。我该怎么办?ty
Dietbacon

7
您也需要在这些视图上调用布局。但是它实际上并不能正常工作,因为这也会使视图刷新动起来。您如何仅在其他视图中为约束调整设置动画?
ngb

3
注意:如果使用UIViewAnimationOptionBeginFromCurrentState布局约束,则会在动画之前设置约束!
罗伯特

12
无需致电layoutIfNeeded每个视图,只需致电[[self.view superview] layoutIfNeeded];
Flying_Banana 2014年

2
@ngb,您需要在动画块更改约束常量。这样,约束随动画而变化,您可以继续使用UIViewAnimationOptionBeginFromCurrentState
伊兰·高丹

86

这对我有效(iOS7和iOS8 +)。单击您要调整的自动布局约束(在界面构建器中,例如顶部约束)。接下来使它成为IBOutlet;

@property (strong, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;

向上动画;

    self.topConstraint.constant = -100;    
    [self.viewToAnimate setNeedsUpdateConstraints]; 
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded]; 
    }];

动画回到原始位置

    self.topConstraint.constant = 0;    
    [self.viewToAnimate setNeedsUpdateConstraints];  
    [UIView animateWithDuration:1.5 animations:^{
        [self.viewToAnimate layoutIfNeeded];
    }];

2
哇!!这实际上确实有效!这个答案让我大开眼界。太谢谢你了!-Erik
Erik van der Neut 2014年

2
@ErikvanderNeut也适合我,很高兴它对我有所帮助。我将从现在开始设置约束动画,而不是框架位置。
DevC

不要错过添加:[containerView layoutIfNeeded]; 它确保在animateWithDuration块之前,所有待处理的布局操作均已完成。
ingconti

11

苹果公司本身有一个很好的教程,讲解了如何在自动布局中使用动画。单击此链接,然后找到名为“示例自动布局”的视频,其中提供了有关自动布局的一些有趣内容,最后一部分是有关如何使用动画的。



1

大多数人使用自动布局来在视图上对项目进行布局,并修改布局约束以创建动画。

无需大量代码即可完成此操作的一种简单方法是在Storyboard中创建要设置动画的UIView,然后在要结束UIView的位置创建一个隐藏的UIView。您可以使用xcode中的预览来确保两个UIView都位于您想要的位置。之后,隐藏结束的UIView并交换布局约束。

如果您不想自己编写,则有一个用于交换布局约束的podfile,称为SBP。

这是一个教程


0

不需要使用更多IBOutlet reference的约束,您可以直接accessupdate已经应用约束,该约束可以由使用库的任何视图应用,Programmatically也可以从Interface Builder任何视图应用KVConstraintExtensionsMaster。该库还管理的Cumulative行为NSLayoutConstraint

在containerView上添加高度约束

 CGFloat height = 200;
 [self.containerView applyHeightConstrain:height];

用动画更新containerView的高度约束

[self.containerView accessAppliedConstraintByAttribute:NSLayoutAttributeHeight completion:^(NSLayoutConstraint *expectedConstraint){
        if (expectedConstraint) {
            expectedConstraint.constant = 100;

            /* for the animation */ 
            [self.containerView  updateModifyConstraintsWithAnimation:NULL];
      }
    }];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.