部分页面需要显示一个工具栏,当键盘出现时,这个工具栏显示在键盘上方。由于使用了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;
}
}