需求:监听键盘frame发生改变时,让inputView跟随键盘显示、隐藏更新位置
在viewDidLoad方法中添加子控件inputView
- (void)viewDidLoad {
[super viewDidLoad];
// 添加底部inputView
self.view.backgroundColor = [UIColor whiteColor];
XYInputView *inputView = [[XYInputView alloc] init];
[self.view addSubview:inputView];
self.inputView = inputView;
// 监听键盘frame发生改变的通知
// 注意: 在这个监听通知的block中要注意循环引用,第一次忘记使用__weak导致当前控制器未被销毁,使用__weak修饰self就解决了
__weak typeof(self) weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardWillChangeFrameNotification
object:nil queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
// 更新inputView的约束
[weakSelf modifyConstraint:note];
}];
}
在viewWillLayoutSubviews方法中给子控件设置约束
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.inputView.translatesAutoresizingMaskIntoConstraints = NO;
// 设置inputView约束
NSDictionary *views = NSDictionaryOfVariableBindings(_inputView);
NSDictionary *metrics = @{@"height": @44};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_inputView]|"
options:0 metrics: metrics views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_inputView(height)]|"
options:0 metrics: metrics views:views]];
}
问题:
由于设置约束使用的是VFL,在键盘frame发生改变时,根据【屏幕的高度】-【键盘结束时的y值】动态改变inputView的y值,但是更新约束时产生问题: 就是键盘显示时inputView会跟随改变y值,当键盘即将隐藏时,inputView并不会改变y值。最后我通过设置inputView.transform解决了
-(void)modifyConstraint:(NSNotification *)note {
// 取出键盘结束时的frame
CGRect endFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat y = kScreenH - endFrame.origin.y; // inputView的y值跟随键盘显示、消失而改变
[UIView animateWithDuration:[note.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^{
self.inputView.transform = CGAffineTransformMakeTranslation(0, -y);
}];
/**************下面是更新约束的代码,这里使用VFL和Masonry都有问题,虽然修改transform可以解决,但是我也要mark下,以后找答案*********************/
// 更改inputView的底部约束
// 根据键盘键盘的y值更新约束会产生问题,就是当键盘隐藏时y为0,但是inputView约束却不改变,未解决,😢
// [self.inputView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-y].active = YES;
// [self.view layoutIfNeeded];
}