需求
一直以来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