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到一个错误的框架。 如果我用updateConstraintsIfNeeded
replace第一个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的答案有一些区别:
- 在调用animation方法(而不是myView上的setNeedsUpdateConstraints)之前,在容器视图上调用layoutIfNeeded。
- 在animation块中设置新的约束。
- 在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。
希望这可以帮助。