假設我們希望將一個視圖在某個時刻移出屏幕,這個視圖的約束有一個負責決定 Y 坐標,它有一個 IBOutlet ,是距離父視圖底部的距離,所以我們要修改它的 constant。
- (void)moveBannerOffScreen {
[UIView animateWithDuration:5
animations:^{
_addBannerDistanceFromBottomConstraint.constant = -32;
}];
bannerIsVisible = FALSE;
}
- (void)moveBannerOnScreen {
[UIView animateWithDuration:5
animations:^{
_addBannerDistanceFromBottomConstraint.constant = 0;
}];
bannerIsVisible = TRUE;
}
視圖確實移動了,就像預期的那樣,但是動畫并沒有發(fā)生。
所以如何讓約束變動以動畫形式呈現(xiàn)呢?
兩個重點:
- 需要在動畫 block 中調(diào)用
layoutIfNeeded。蘋果實際上建議在動畫 block 之前調(diào)用一次,以確保所有待處理的布局操作都已完成 - 需要在父視圖(例如 self.view)上調(diào)用它,而不是那個被附加約束的子視圖。這么做會更新所有有約束的視圖,也會讓其它與這個被改變約束的視圖有約束關系的視圖產(chǎn)生動畫。(例如視圖 B 貼在 視圖 A 的底部,如果你改變了視圖 A 的頂部偏移量,你希望 B 也能有動畫)
所以要這么做:
Objective-C
- (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;
}
Swift 3
_addBannerDistanceFromBottomConstraint.constant = 0
UIView.animate(withDuration: 5) {
self.view.layoutIfNeeded()
}