我正在使用AdBannerView
更新旧应用,当没有广告时,它会从屏幕上滑落。当有广告时,它会在屏幕上滑动。基本的东西。
旧样式,我在动画块中设置框架。新风格,我有一个确定 Y 位置的约束的IBOutlet
,在这种情况下它是与 superview 底部的距离,并修改常量。
- (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
方法为子视图约束设置动画怎么办?
[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
一部分,用一对UITextField
切换子视图,并带有一个简单而细微的折叠动画(0.2 秒长)。如上所述,在 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