当Auto Layout遇上动画(一)
本文主要介绍自己在项目开发过程中, 遇到的关于使用auto layout布局, 然后实现view的frame变化的动画, 会出现问题, 简单地说, 就是我们设置的动画效果会无效, 特别是当我们在当前viewController使用push的方式来展现另外一个controller, 这时候view动画失效, 会还原view的frame.
大致而言, 就是这样一个问题, 下面详细解释一下:
首先, 我们现在一般都使用xib文件实现布局, 当然也就少不了接触auto layout, 但是当我们需要给一个view添加动画的时候, 我们通常会这样做:
1.使用xib文件添加一个view
2.给view添加动画
[UIView animateWithDuration:0.25 animations:^{
CGRect originalFrame = self.animationView.frame;
originalFrame.origin.y /= 2;
originalFrame.size.width /= 2;
originalFrame.size.height /= 2;
self.animationView.frame = originalFrame;
} completion:^(BOOL finished) {
NSLog(@"%s--%@", __FUNCTION__, NSStringFromCGRect(self.animationView.frame));
}];
就像上面这样, 简单修改frame, 来达到我们的动画效果:
动画前的效果:
动画后的效果:
其实到这里我们就已经发现问题了, 我们本来设置的view的约束的水平居中, 但是动画后发现并没有, 这也是auto layout遇上动画的一个问题, 但是更严重的问题还在后面:
接下来, 我们想要push出一个viewController, 当我们push的时候就会发现问题了, 添加动画的view还原了, 真的还原了, 之前添加的动画失效了, 这到底是什么原因?
其实, 查找问题的方法很简单, 那就是在viewController的生命周期中, 打印出view的frame, 看看到底是哪个阶段发生了变化:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"%s--%@", __FUNCTION__, NSStringFromCGRect(self.animationView.frame));
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(@"%s--%@", __FUNCTION__, NSStringFromCGRect(self.animationView.frame));
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
NSLog(@"%s--%@", __FUNCTION__, NSStringFromCGRect(self.animationView.frame));
}
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
NSLog(@"%s--%@", __FUNCTION__, NSStringFromCGRect(self.animationView.frame));
}
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
NSLog(@"%s--%@", __FUNCTION__, NSStringFromCGRect(self.animationView.frame));
}
- (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
NSLog(@"%s--%@", __FUNCTION__, NSStringFromCGRect(self.animationView.frame));
}
结果分析:
2016-06-20 22:19:39.603 AutoLayoutAnimationTest[3794:591399] -[ViewController viewWillDisappear:]--{{107, 82}, {100, 100}}
2016-06-20 22:19:39.605 AutoLayoutAnimationTest[3794:591399] -[ViewController viewWillLayoutSubviews]--{{107, 82}, {100, 100}}
2016-06-20 22:19:39.605 AutoLayoutAnimationTest[3794:591399] -[ViewController viewDidLayoutSubviews]--{{107, 164}, {200, 200}}
2016-06-20 22:19:40.106 AutoLayoutAnimationTest[3794:591399] -[ViewController viewDidDisappear:]--{{107, 164}, {200, 200}}
从结果中我们可以很清楚的看到是在viewDidLayoutSubviews中发生了变化, 关于viewDidLayoutSubviews简单来说, 就是重新布局view的子视图的, 至于更详细的解释大家可以自行查找, 这里给出本人在stackoverflow上找到解释Changing a frame in viewDidLayoutSubviews
大家可以认真看完这个解释, 里面也解释了关于为什么使用auto layout的时候, 设置frame动画会失效, 其实就是viewDidLayoutSubviews的时候, 会按照xib中的约束重新布局, 之前设置的frame会直接被忽略, 这也就是之前问题的根源所在.
因此, 当我们使用auto-layout布局的时候, 如果也想使用动画, 那么建议给约束添加动画, 不要直接修改frame实现动画, 不然就会出现上面的问题, 至于约束动画, 建议大家可以使用facebook的pop来做动画, 里面有专门针对约束的动画类型kPOPLayoutConstraintConstant, 使用起来也很方便.