1.在keyboardWillShow和keyboardWillHide方法中做键盘处理
// 监听键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
#pragma mark - 键盘处理
- (void)keyboardWillShow:(NSNotification *)note {
// 取出键盘最终的frame
CGRect rect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 取出键盘弹出需要花费的时间
double duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 修改约束
self.bottomSpacing.constant = rect.size.height;
[UIView animateWithDuration:duration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)note {
// 取出键盘弹出需要花费的时间
double duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 修改约束
self.bottomSpacing.constant = 0;
[UIView animateWithDuration:duration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
2.在keyboardWillChangeFrame方法中做键盘处理
// 监听键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
#pragma mark - 键盘处理
- (void)keyboardWillChangeFrame:(NSNotification *)note {
// 取出键盘最终的frame
CGRect rect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 取出键盘弹出需要花费的时间
double duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 修改约束
self.bottomSpacing.constant = [UIScreen mainScreen].bounds.size.height - rect.origin.y;
[UIView animateWithDuration:duration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
3.通过tranform做键盘处理
// 监听键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
#pragma mark - 键盘处理
- (void)keyboardWillChangeFrame:(NSNotification *)note {
// 取出键盘最终的frame
CGRect rect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 取出键盘弹出需要花费的时间
double duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 修改transform
[UIView animateWithDuration:duration animations:^{
CGFloat ty = [UIScreen mainScreen].bounds.size.height - rect.origin.y;
self.view.transform = CGAffineTransformMakeTranslation(0, - ty);
}];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
4.关于layoutIfNeeded
对于layoutIfNeeded本人浅谈下自己的理解,首先我们要了解为何在用到用到constraint的动画时以下代码无法实现动画的功能:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[UIView animateWithDuration:2.0 animations:^{
self.blueViewH.constant = 80;
}];
}
而我们直接使用frame的时候动画是可以实现的:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[UIView animateWithDuration:2.0 animations:^{
CGRect size =self.blueView.frame;
size.size.height = 80;
self.blueView.frame = size;
}];
}
说明,我们所调用的方法是正确的,那么我们可以大胆的假设"self.blueViewH.constant = 80;"在这句赋值并没有在该方法中完成,从而导致动画并没有实现;而要进行Constraint动画则需要对NSLayoutConstraint的对象赋值之后调用layoutIfNeeded方法才能实现动画(由于Xcode改版后调用layoutIfNeeded方法只会刷新子控件键,因此要使用必须通过它的父类):
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.blueViewW.constant = 80;
[UIView animateWithDuration:2.0 animations:^{
[self.view layoutIfNeeded];
}];
}
通过两个能够实现动画的代码比较,我们就可以推测出NSLayoutConstraint的本质就是在系统底层转换为frame,并且NSLayoutConstraint的转换还不是在你赋值的时候就转换完成,而是极可能在某一方法结束后才进行转换;因此我们调用layoutIfNeeded方法对"self.blueViewW.constant = 80;"代码进行强制刷新的时候便能实现该动画了.
总之,layoutIfNeeded在需要重新布局的时候立即刷新进行重新布局,不受其他因素影响.