需求
一直以來iOS的 Autolayout 都是一個很不錯的功能,結合第三方 Masonry 可以節省很多工作成本。但是如果使用 Autolayout 來製作動畫,那麼就需要注意一下。不然就會像我一樣,遇坑踩坑,越陷越深。
使用xib實現動畫
使用情景:自定義一個UIView ViewA
,實現由下往上彈窗效果。
效果如下
假如我們是使用xib建立自定義彈窗檢視,一般我們都會在xib上做好了約束的條件,之後在.m檔案裡面實現檢視的初始化操作。
實現動畫的原則是,在ViewA
執行動畫之前,需要將ViewA
最終約束條件設定好,之後在執行動畫程式碼塊裡面只需要呼叫layoutIfNeeded
即可。
另外呼叫layoutIfNeeded
方法的物件必須是ViewA
的父檢視,不然會出現ViewA
的子檢視跟著執行動畫的情況。
如下面的程式碼中,ViewA
的父檢視就是window
,所以呼叫layoutIfNeeded
方法的物件是window
- (instancetype)init {
self = [[[NSBundle mainBundle] loadNibNamed:@"DDJoinView" owner:self options:nil] lastObject];
if (self) {
self.frame = CGRectMake(0, kScreenHeight, kScreenWidth, 195);
}
return self;
}
- (void)show {
UIWindow *window = [UIApplication sharedApplication].keyWindow;
_bgView = [[UIButton alloc] init];
_bgView.backgroundColor = UIColorHex(0x000000);
_bgView.alpha = 0.25;
_bgView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
[_bgView addTarget:self action:@selector(close:) forControlEvents:UIControlEventTouchUpInside];
[window addSubview:_bgView];
[window addSubview:self];
[self mas_updateConstraints:^(MASConstraintMaker *make) {
(void)make.left;
(void)make.centerX;
make.height.offset(195);
make.bottom.offset(0);
}];
[UIView animateWithDuration:0.3f animations:^{
[window layoutIfNeeded];
}];
}
#pragma mark - 關閉
- (void)close:(id)sender {
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[self mas_updateConstraints:^(MASConstraintMaker *make) {
(void)make.left;
(void)make.centerX;
make.height.offset(195);
make.bottom.offset(195);
}];
[UIView animateWithDuration:0.3f animations:^{
[window layoutIfNeeded];
} completion:^(BOOL finished) {
for (UIView *v in [self subviews]) {
[v removeFromSuperview];
}
[self removeFromSuperview];
[_bgView removeFromSuperview];
}];
}
複製程式碼
總結
//...
//執行下面動畫前,設定自定義view的最終位置的約束條件
//...
[UIView animateWithDuration:0.3f animations:^{
[xxx layoutIfNeeded];
} completion:^(BOOL finished) {
//do something
}];
複製程式碼
再一次感謝您花費時間閱讀這篇文章!
微博: @Danny_呂昌輝
部落格: SuperDanny