我如何动画约束更改?
我正在使用AdBannerView
更新旧应用,当没有广告时,它会滑出屏幕。 有广告时,它会在屏幕上滑动。 基本的东西。
旧样式,我在一个动画块中设置框架。 新的风格,我有一个IBOutlet
的约束,它决定了Y的位置,在这种情况下,它是从超级视图底部的距离,并修改常数。
- (void)moveBannerOffScreen {
[UIView animateWithDuration:5
animations:^{
_addBannerDistanceFromBottomConstraint.constant = -32;
}];
bannerIsVisible = FALSE;
}
- (void)moveBannerOnScreen {
[UIView animateWithDuration:5
animations:^{
_addBannerDistanceFromBottomConstraint.constant = 0;
}];
bannerIsVisible = TRUE;
}
横幅的移动与预期完全相同,但没有动画。
更新:我重新观看了包含动画的WWDC12视频“掌握自动布局的最佳实践”。 它讨论了如何使用CoreAnimation
更新约束。
我已经尝试了下面的代码,但获得完全相同的结果。
- (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;
}
在附注中,我已经检查了很多次,并且正在主线程上执行。
两个重要提示:
您需要在动画块中调用layoutIfNeeded
。 Apple实际上建议您在动画块之前调用一次,以确保所有挂起的布局操作都已完成
你需要在父视图 (比如self.view
)上专门调用它,而不是附加了约束的子视图。 这样做会更新所有受限制的视图,包括动画其他视图,这些视图可能会受限于您更改约束的视图(例如,视图B附加到视图A的底部,并且您刚刚更改视图A的顶部偏移并且您希望视图B用它制作动画)
尝试这个:
Objective-C的
- (void)moveBannerOffScreen {
[self.view layoutIfNeeded];
[UIView animateWithDuration:5
animations:^{
self._addBannerDistanceFromBottomConstraint.constant = -32;
[self.view layoutIfNeeded]; // Called on parent view
}];
bannerIsVisible = FALSE;
}
- (void)moveBannerOnScreen {
[self.view layoutIfNeeded];
[UIView animateWithDuration:5
animations:^{
self._addBannerDistanceFromBottomConstraint.constant = 0;
[self.view layoutIfNeeded]; // Called on parent view
}];
bannerIsVisible = TRUE;
}
斯威夫特3
UIView.animate(withDuration: 5) {
self._addBannerDistanceFromBottomConstraint.constant = 0
self.view.layoutIfNeeded()
}
我非常感谢所提供的答案,但我认为这样做会更好一点。
文档中的基本块动画
[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
方法来动画子视图约束呢?
调用子视图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];
}
AutoLayout指南留下了许多不足之处,但值得一读。 我自己使用这个作为一个UISwitch
一部分,它使用一对简单的细微折叠动画(0.2秒长)切换一对UITextField
的子视图。 如上所述,子视图的约束正在UIView子类的updateConstraints方法中处理。
通常,您只需更新约束并在动画块内调用layoutIfNeeded
。 这可以是改变.constant
一个的属性NSLayoutConstraint
,加入除去约束(iOS的7),或改变.active
约束的属性(的iOS 8和9)。
示例代码:
[UIView animateWithDuration:0.3 animations:^{
// Move to right
self.leadingConstraint.active = false;
self.trailingConstraint.active = true;
// Move to bottom
self.topConstraint.active = false;
self.bottomConstraint.active = true;
// Make the animation happen
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
样本设置:
争议
关于约束是应该在动画块之前还是在其内部进行更改存在一些问题(请参阅前面的答案)。
以下是教授iOS的Martin Pilkington和编写Auto Layout的Ken Ferry之间的Twitter对话。 Ken解释说,尽管改变动画块之外的常量现在可以工作,但这并不安全,他们应该真的在动画块内进行更改。 https://twitter.com/kongtomorrow/status/440627401018466305
动画:
示例项目
以下是一个简单的项目,展示如何将视图变成动画。 它使用Objective C并通过更改多个约束的.active
属性来为视图添加动画。 https://github.com/shepting/SampleAutoLayoutAnimation
上一篇: How do I animate constraint changes?
下一篇: How to support both iPad and iPhone retina graphics in universal apps