animation - 如何动画显示被约束的更改?

  显示原文与译文双语对照的内容

我正在用 AdBannerView 更新一个旧的应用,当没有广告时,它就会滑出屏幕。 当有一个广告在屏幕上播放时。 基本内容。

旧样式,我在动画块中设置框架。 新样式,我有一个 IBOutlet 到约束的约束,在这种情况下,它与superview的底部是距离,并修改常量。


- (void)moveBannerOffScreen {
 [UIView animateWithDuration:5
 animations:^{
 _addBannerDistanceFromBottomConstraint.constant = -32;
 }];
 bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
 [UIView animateWithDuration:5
 animations:^{
 _addBannerDistanceFromBottomConstraint.constant = 0;
 }];
 bannerIsVisible = TRUE;
}

横幅移动,就像预期的那样,但没有动画。

更新: i re-watched WWDC12视频"掌握自动布局的最佳实践",涵盖动画。 讨论如何使用 CoreAnimation 更新约束。

enter image description hereenter image description here

我试过下面的代码,但得到的结果完全相同。


- (void)moveBannerOffScreen {
 _addBannerDistanceFromBottomConstraint.constant = -32;
 [UIView animateWithDuration:2
 animations:^{
 [self.view setNeedsLayout];
 }];
 bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen {
 _addBannerDistanceFromBottomConstraint.constant = 0;
 [UIView animateWithDuration:2
 animations:^{
 [self.view setNeedsLayout];
 }];
 bannerIsVisible = TRUE;
}

顺便说一下,我已经检查了很多次,它在主线程上执行。

时间:

两个重要说明:

  1. 你需要在动画块中调用 layoutIfNeededApple实际上建议你在动画块之前调用它一次,以确保所有待定的布局操作都已经完成
  2. 你需要在的父视图 ( 例如。 self.view ),而不是具有附加约束的子视图。 这样做将更新所有 约束视图,包括做动画中的其他视图可能会被约束到视图的用户已经更改约束( 例如 视图B 附加到视图的底部,你只更改了偏移量的视图顶部,你希望视图B 可以使用它进行动画处理

尝试这个:


- (void)moveBannerOffScreen {
 [self.view layoutIfNeeded];

 _addBannerDistanceFromBottomConstraint.constant = -32;
 [UIView animateWithDuration:5
 animations:^{
 [self.view layoutIfNeeded];//Called on parent view
 }];
 bannerIsVisible = FALSE;
}

- (void)moveBannerOnScreen { 
 [self.view layoutIfNeeded];

 _addBannerDistanceFromBottomConstraint.constant = 0;
 [UIView animateWithDuration:5
 animations:^{
 [self.view layoutIfNeeded];//Called on parent view
 }];
 bannerIsVisible = TRUE;
}

提供的答案让我感动,但我认为这将是很高兴获得了一点深入的。

来自文档的基本块动画


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

但这其实是一个非常简单的场景。 假如我想经由 updateConstraints subview约束动画方法?

调用 subviews updateConstraints方法的动画块


[self.view layoutIfNeeded];
[self.subView setNeedsUpdateConstraints];
[self.subView updateConstraintsIfNeeded];
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionLayoutSubviews animations:^{
 [self.view layoutIfNeeded];
} completion:nil];

updateConstraints方法在UIView子类中被重写,并且必须在方法结束时调用 super 。


- (void)updateConstraints
{
//Update some constraints

 [super updateConstraints];
}

在自动布局指南 不尽人意但很值得研究。 我自己正在用这作为 UISwitch的一部分,用于切换一个subview和一对 UITextField 是以一种简单而精致的折叠动画( 0.2秒长) 。 subview的约束正在UIView子类updateConstraints方法中处理,如上所述。


//Step 1, update your constraint
self.myOutletToConstraint.constant = 50;//New height (for example)

//Step 2, trigger animation
[UIView animateWithDuration:2.0 animations:^{

//Step 3, call layoutIfNeeded on your animated view's parent
 [self.view layoutIfNeeded];
}];

我试图对约束进行动画处理,但并不难找到一个好的解释。

其他的回答是完全真实的: 你需要调用 [self.view layoutIfNeeded];animateWithDuration: animations: 内。 然而,另一个重要的一点是,你需要为每个你想要动画的NSLayoutConstraint 提供指针。

我在GitHub中创建了一个例子。

有一篇文章讨论了这一点: http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was

在其中,他像这样编码:


- (void)handleTapFrom:(UIGestureRecognizer *)gesture {
 if (_isVisible) {
 _isVisible = NO;
 self.topConstraint.constant = -44.;//1
 [self.navbar setNeedsUpdateConstraints];//2
 [UIView animateWithDuration:.3 animations:^{
 [self.navbar layoutIfNeeded];//3
 }];
 } else {
 _isVisible = YES;
 self.topConstraint.constant = 0.;
 [self.navbar setNeedsUpdateConstraints];
 [UIView animateWithDuration:.3 animations:^{
 [self.navbar layoutIfNeeded];
 }];
 }
}

希望有帮助。

...