我正在更新一个带有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;
}
横幅的移动和预期的完全一样,但是没有动画。
更新:我重新看了WWDC 12演讲《掌握自动布局的最佳实践》,其中包括动画。它讨论了如何使用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。这可以是改变NSLayoutConstraint的.constant属性,添加remove约束(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
使用Xcode 8.3.3测试Swift 3的解决方案:
self.view.layoutIfNeeded()
self.calendarViewHeight.constant = 56.0
UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
只要记住那个自我。calendarViewHeight是一个引用自customView (CalendarView)的约束。我在self上调用了. layoutifneeded()。view和NOT在self。calendarview上
希望这对你有所帮助。