部分页面需要显示一个工具栏,当键盘出现时,这个工具栏显示在键盘上方。由于使用了IQKeyboardManager,导致有的页面iOS12.5.6系统的手机出现首次键盘高度比实际低44像素,而iOS14.7.1系统的手机出现首次键盘高度比实际低44像素并且有时出现最后收到键盘隐藏通知但是实际显示了键盘。
收到通知直接设置工具栏的frame,也过于突兀,最好采用做动画的方式显示工具栏,动画完成时再修正键盘高度,这样能部分解决上面的那两个问题。
那键盘的动画时间是0.25秒,可以在键盘通知里获取到这个参数。那键盘的实际高度从哪里获取呢?经过观察View UI Herarchy发现有键盘的页面都有UIInputSetContainerView,键盘的总高度就是UIInputSetHostView的总高度。只是iOS13及跟高的系统,键盘是在第二个窗口的UIInputWindowController中,而比iOS13低的版本在第是哪个窗口的UITextEffectsWindow中。具体的实现如下:
增加键盘显示通知:
//监听键盘的变化 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardChange:) name:UIKeyboardWillShowNotification object:nil];
键盘通知处理:
- (void)keyBoardChange:(NSNotification *)notification { //获取键盘的高度 NSDictionary *userInfo = [notification userInfo]; NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]; CGRect keyboardRect = [aValue CGRectValue]; CGFloat height = keyboardRect.size.height; //获取动画时间I CGFloat animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; NSLog(@"animationDuration:%f,height:%f",animationDuration,height); if(self.keyBoardChangeBlock) { self.keyBoardChangeBlock(height, animationDuration); } }
键盘显示动画与修正:
- (LCCommentToolView *)comTool { if (_comTool == nil) { _comTool = [[LCCommentToolView alloc] initWithFrame:CGRectMake(0, 0, KScreenW, BaseSize(100))] ; [_comTool setCorner:UIRectCornerTopLeft|UIRectCornerTopRight cornerSize:BaseSize(15) forRect:CGRectMake(0, 0, KScreenW, BaseSize(100))]; DYWeakSelf; [_comTool setKeyBoardChangeBlock:^(CGFloat height, CGFloat animationDuration) { if (DYGlobleData.isLogin) { if(animationDuration <= 0) { //防范式编程,理论不会出现 weakSelf.bgV.hidden = NO; } else { weakSelf.bgV.hidden = (height<=0); [UIView animateWithDuration:animationDuration animations:^{ if((height<=0)) { [weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(BaseSize(100)); make.width.mas_equalTo(KScreenW); make.bottom.mas_equalTo(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))); }]; [weakSelf.comTool updateCommentTVWithShift:(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))+(BR_BOTTOM_MARGIN?24:0))]; } else { [weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(BaseSize(100)); make.width.mas_equalTo(KScreenW); make.bottom.mas_equalTo(-height); }]; [weakSelf.comTool updateCommentTVWithShift:0]; } [weakSelf layoutIfNeeded]; } completion:^(BOOL finished) { CGFloat keyboardHeight = [weakSelf displayKeyboardDockView]; if(keyboardHeight > 0) { [weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(BaseSize(100)); make.width.mas_equalTo(KScreenW); make.bottom.mas_equalTo(-keyboardHeight); }]; [weakSelf.comTool updateCommentTVWithShift:0]; } else { [weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(BaseSize(100)); make.width.mas_equalTo(KScreenW); make.bottom.mas_equalTo(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))); }]; [weakSelf.comTool updateCommentTVWithShift:(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))+(BR_BOTTOM_MARGIN?24:0))]; } [weakSelf layoutIfNeeded]; }]; } } else { weakSelf.bgV.hidden = YES; [weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(BaseSize(100)); make.width.mas_equalTo(KScreenW); make.bottom.mas_equalTo(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))); }]; [weakSelf.comTool updateCommentTVWithShift:(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))+(BR_BOTTOM_MARGIN?24:0))]; }; }]; } return _comTool; }
识别键盘是否在显示和获取键盘高度,键盘高为0.0是键盘隐藏:
- (CGFloat)displayKeyboardDockView{ UIWindow *keyboardWindow = [[[UIApplication sharedApplication] windows] objectAtSafeIndex:1]; UIView *keyboardContainerView; UIView *keyboardHostView; if (@available(iOS 13.0, *)) { for(int i = 0; i < [keyboardWindow.subviews count]; i++) { keyboardContainerView = [keyboardWindow.subviews objectAtIndex:i]; UIViewController *nextResponder = (UIViewController*)[keyboardContainerView nextResponder]; if(([nextResponder isKindOfClass:NSClassFromString(@"UIWindow")])) { NSLog(@"[nextResponder.subviews count]:%d, nextResponder.subviews:%@", [keyboardWindow.subviews count], keyboardWindow.subviews); } //寻找keyboardWindow层的UIInputWindowController else if ([nextResponder isKindOfClass:NSClassFromString(@"UIInputWindowController")]) { for(int y = 0; y < [nextResponder.view.subviews count]; y++) { //寻找UIInputWindowController层的UIInputSetContainerView if([[keyboardContainerView description] hasPrefix:@"<UIInputSetContainerView"] == YES){ for(int t = 0; t < [keyboardContainerView.subviews count]; t++) { keyboardHostView = [keyboardContainerView.subviews objectAtIndex:t]; //寻找UIInputSetContainerView层的UIInputSetHostView if([[keyboardHostView description] hasPrefix:@"<UIInputSetHostView"] == YES){ NSLog(@"keyboardHostView description:%@,keyboardHostView.isHidden:%d,[keyboardHostView.subviews count],[keyboardHostView.subviews count],keyboardHostView.frame.size.height:%f,keyboardHostView.frame.origin.y:%f, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height):%d", [keyboardHostView description],keyboardHostView.isHidden,[keyboardHostView.subviews count], keyboardHostView.frame.size.height,keyboardHostView.frame.origin.y, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height)); if (lroundl(keyboardHostView.frame.origin.y) != lroundl(([[UIScreen mainScreen] bounds].size.height))) { return keyboardHostView.frame.size.height; } else { return 0.0; } } } } } } } return 0.0; } else { keyboardWindow = [[[UIApplication sharedApplication] windows] objectAtSafeIndex:2]; if(keyboardWindow && [keyboardWindow isKindOfClass:NSClassFromString(@"UITextEffectsWindow")] && !isCommonUnitEmptyArray(keyboardWindow.subviews)) { keyboardContainerView = [keyboardWindow.subviews objectAtSafeIndex:0]; if(keyboardContainerView && ([[keyboardContainerView description] hasPrefix:@"<UIInputSetContainerView"] == YES)) { for(int t = 0; t < [keyboardContainerView.subviews count]; t++) { keyboardHostView = [keyboardContainerView.subviews objectAtIndex:t]; //寻找UIInputSetContainerView层的UIInputSetHostView if([[keyboardHostView description] hasPrefix:@"<UIInputSetHostView"] == YES){ NSLog(@"keyboardHostView description:%@,keyboardHostView.isHidden:%d,[keyboardHostView.subviews count],[keyboardHostView.subviews count],keyboardHostView.frame.size.height:%f,keyboardHostView.frame.origin.y:%f, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height):%d", [keyboardHostView description],keyboardHostView.isHidden,[keyboardHostView.subviews count], keyboardHostView.frame.size.height,keyboardHostView.frame.origin.y, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height)); if (lroundl(keyboardHostView.frame.origin.y) != lroundl(([[UIScreen mainScreen] bounds].size.height))) { return keyboardHostView.frame.size.height; } else { return 0.0; } } } } } return 0.0; } }