NSLayoutConstraints是可以animation的吗?

我正在尝试对一些视图进行animation处理,以使它们被景观中的巨型键盘所阻挡。 如果我简单地为框架设置animation效果,效果会很好,但是其他人则认为这样做会适得其反,而我应该更新NSLayoutConstraints。 但是,他们似乎不是可以animation的。 有没有人得到他们的成功?

//heightFromTop is an NSLayoutConstraint referenced from IB [UIView animateWithDuration:0.25 animations:^{ self.heightFromTop.constant= 550.f; }]; 

结果是立即跳到有问题的高度。

只要按照这个确切的模式:

 self.heightFromTop.constant = 550.0f; [myView setNeedsUpdateConstraints]; [UIView animateWithDuration:0.25f animations:^{ [myView layoutIfNeeded]; }]; 

self.heightFromTop是添加myView的视图。 你的视图是“跳跃”的,因为你在animation块中做的唯一的事就是设置约束,这不会立即导致布局。 在你的代码中,设置heightFromTop.constant之后,布局会在下一次运行循环中发生,到那时你已经超出了animation块的范围。

在Swift 2中:

 self.heightFromTop.constant = 550 myView.setNeedsUpdateConstraints() UIView.animateWithDuration(0.25, animations: { myView.layoutIfNeeded() }) 

苹果的build议方式有点不同( 请参阅“自动布局制作的animation更改”一节中的示例 )。 首先你需要在animation之前调用layoutIfNeeded。 然后将animation内容添加到animation块中,然后再次调用layoutIfNeeded。 对于像我这样的过渡到自动布局的人来说,它与我们之前使用animation块内的帧进行animation的方式更类似。 我们只需要调用layoutIfNeeded两次 – 在animation之前和animation之后:

 [self.view layoutIfNeeded]; // Ensures that all pending layout operations have been completed [UIView animateWithDuration:1.0f animations:^{ // Make all constraint changes here self.heightFromTop.constant= 550.f; [self.view layoutIfNeeded]; // Forces the layout of the subtree animation block and then captures all of the frame changes }]; 

我试过@ Centurion的方法,但不知何故,如果从故事板中加载,我的视图会animation到一个错误的框架。 如果我用updateConstraintsIfNeededreplace第一个layoutIfNeeded ,问题就消失了,尽pipe我不知道为什么。 如果任何人可以给解释,将不胜感激。

 [self.view updateConstraintsIfNeeded]; [UIView animateWithDuration:1.0 animations:^{ self.myConstraint.constant= 100; [self.view layoutIfNeeded]; }]; 

我有一个类似的问题,这个线程是一个很好的帮助,以通过它。

erurainon的回答使我走上正轨,但我想提出一个稍微不同的答案。 从erurainonbuild议的代码不适合我,因为我仍然有一个跳跃,而不是animation过渡。 cnotethegr8提供的链接给了我工作的答案:

自动布局指南 https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html (一直到页面底部)。

与erurainon的答案有一些区别:

  1. 在调用animation方法(而不是myView上的setNeedsUpdateConstraints)之前,在容器视图上调用layoutIfNeeded。
  2. 在animation块中设置新的约束。
  3. 在animation方法的容器视图上调用layoutIfNeeded(设置约束之后),而不是在myView上。

这将坚持在上面的链接苹果build议的模式。

一个例子

我想animation一个特定的视图,closures或扩大它点击一个button。 由于我使用自动布局,并不想在代码中硬编码任何维度(在我的情况下,高度),我决定捕获viewDidLayoutSubviews中的高度。 使用自动布局时,您需要使用此方法而不是viewWillAppear。 由于viewDidLayoutSubviews可能会被调用很多次,所以我使用BOOL让我知道初始化的第一个执行。

 // Code snippets @property (weak, nonatomic) IBOutlet UIView *topView; // Container for minimalView @property (weak, nonatomic) IBOutlet UIView *minimalView; // View to animate @property (nonatomic) CGFloat minimalViewFullHeight; // Original height of minimalView @property (weak, nonatomic) IBOutlet NSLayoutConstraint *minimalViewHeightConstraint; @property (nonatomic) BOOL executedViewDidLayoutSubviews; - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // First execution of viewDidLayoutSubviews? if(!self.executedViewDidLayoutSubviews){ self.executedViewDidLayoutSubviews = YES; // Record some original dimensions self.minimalViewFullHeight = self.minimalView.bounds.size.height; // Setup our initial view configuration & let system know that // constraints need to be updated. self.minimalViewHeightConstraint.constant = 0.0; [self.minimalView setNeedsUpdateConstraints]; [self.topView layoutIfNeeded]; } } 

调整完整的操作片段

 // An action to close our minimal view and show our normal (full) view - (IBAction)resizeFullAction:(UIButton *)sender { [self.topView layoutIfNeeded]; [UIView transitionWithView:self.minimalView duration:1.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.minimalViewHeightConstraint.constant = 0.0; // Following call to setNeedsUpdateConstraints may not be necessary [self.minimalView setNeedsUpdateConstraints]; [self.topView layoutIfNeeded]; } completion:^(BOOL finished) { ; }]; // Other code to show full view // ... } 

调整小动作片段

 // An action to open our minimal view and hide our normal (full) view - (IBAction)resizeSmallAction:(UIButton *)sender { [self.topView layoutIfNeeded]; [UIView transitionWithView:self.minimalView duration:1.0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ self.minimalViewHeightConstraint.constant = self.minimalViewFullHeight; [self.minimalView setNeedsUpdateConstraints]; [self.topView layoutIfNeeded]; } completion:^(BOOL finished) { ; }]; // Other code to hide full view // ... } 

如果你愿意,你可以使用animateWithDuration而不是transitionWithView。

希望这可以帮助。