UIKeyboardWillShowNotification时返回的iOS键盘高度不正确

19
我正在尝试在键盘弹出时滚动我的文本视图。我试图遵循苹果自己的教程https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html。但与其使用滚动视图和框架不同,我使用了自动布局,但总体思路是相同的(订阅键盘通知,并相应地动画化布局约束)。然而,当我显示键盘时,文本视图和键盘之间存在间隙:(这是来自土耳其键盘的屏幕截图,但是所有已安装的键盘,包括自定义键盘,都存在相同的标记为红色的间隙)。 (来自iPhone 6 Plus的屏幕截图,但此问题在其他屏幕尺寸上也存在)

enter image description here

我看到了在iOS8中无法正确获取键盘高度的值,我尝试使用UIKeyboardFrameEndUserInfoKeyUIKeyboardFrameBeginUserInfoKey,但它们都导致同样的间隙。我尝试侦听UIKeyboardWillShowNotificationUIKeyboardDidShowNotification事件,但仍然得到相同的间隙。我认为这个间隙与iOS 8上某些键盘的建议有关,但当没有建议时,它不应该报告带有建议的键盘大小。
以下是我的代码:
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self registerForKeyboardNotifications];
}

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeShown:)
                                                 name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];

}

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWillBeShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGRect kb = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    float height = kb.size.height;
    sendZoneBottomConstraint.constant = height;
    [UIView animateWithDuration:.2 animations:^{
        [self.view layoutIfNeeded];
    }];
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    sendZoneBottomConstraint.constant = 0;
    [UIView animateWithDuration:.2 animations:^{
        [self.view layoutIfNeeded];
    }];
}

sendZoneBottomConstraint 是指底部视图与底部布局向导的底部间距。

更新:我尝试将键盘矩形从窗口坐标系更改为我的视图坐标系,但没有任何变化。这是我尝试过的:

CGRect kb = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
kb = [self.view.window convertRect:kb toView:self.view];
float height = kb.size.height;

更新,第二版:我也看到了iOS 8方向更改:键盘框架显示不正确,但我在iPhone 5s iOS 7.1模拟器上也遇到了这个问题,所以这不仅是iOS 8的问题。我该如何解决这个问题?在iOS 8世界中,我绝对不想硬编码任何键盘高度值。

更新,第三版:我还尝试了英文键盘,无论是开启还是关闭建议功能,它仍然会根据键盘的总大小出现,因此与建议/自动完成视图无关:

enter image description here enter image description here


2
你是否将键盘的框架转换为适当的本地视图坐标?请使用一些相关代码更新你的问题,说明你遇到的问题。 - rmaddy
@rmaddy,我已经包含了代码。如何将键盘的框架转换为本地视图坐标?我的意思是,我知道我会使用convertRect:[to | from] View:,但是从哪个视图到我的本地视图的坐标? - Can Poyrazoğlu
1
@CanPoyrazoğlu:我通常从self.window进行转换。 - Linuxios
@rmaddy 改变坐标没有改变任何东西,请查看我的更新问题。 - Can Poyrazoğlu
2
我觉得你在选项卡视图控制器中有一个布局约束到底部布局指南。如果是这样,如果你考虑一下,解决方案就很简单。 - mostruash
显示剩余8条评论
2个回答

24

也许你正在使用选项卡栏控制器,如果是的话,在键盘弹出后调整视图的边距时,需要计算不包括选项卡栏高度的底部边距。

您可以使用以下代码找到选项卡栏的高度:

self.tabBarController?.tabBar.frame.height

1
谢谢,我有同样的问题,这就是答案。 - eilas
就这样!谢谢。 - Thomás Pereira

-1

为了实现稳健的键盘高度计算,您可以使用以下方法:

注意:我从IQKeyboard中借用了一些逻辑来解决这个问题。

CGRect kbFrame = [[aNotification userInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue];

CGRect screenSize = [[UIScreen mainScreen] bounds];

CGRect intersectRect = CGRectIntersection(kbFrame, screenSize);//Calculating actual keyboard displayed size, keyboard frame may be different when hardware keyboard is attached (Bug ID: #469) (Bug ID: #381)

CGSize kbSize;
if (CGRectIsNull(intersectRect)) {
    kbSize = CGSizeMake(screenSize.size.width, 0);
} else {
    kbSize = intersectRect.size;
}

//

UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (rootViewController) {
    if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController *navigationController = (UINavigationController *)rootViewController;
        UIViewController *nextRootViewController = [[navigationController viewControllers] lastObject];
        if (nextRootViewController) {
            rootViewController = nextRootViewController;
            continue;
        } else {
            break;
        }
    }
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController *tabBarController = (UITabBarController *)rootViewController;
        UIViewController *nextRootViewController = tabBarController.selectedViewController;
        if (nextRootViewController) {
            rootViewController = nextRootViewController;
            continue;
        } else {
            break;
        }
    }
    if (!rootViewController.presentedViewController) {
        break;
    }
    rootViewController = (UIViewController *)rootViewController.presentedViewController;
}

//

CGFloat navigationBarAreaHeight = [[UIApplication sharedApplication] statusBarFrame].size.height + rootViewController.navigationController.navigationBar.frame.size.height;
CGFloat layoutAreaHeight = rootViewController.view.layoutMargins.top;

CGFloat topLayoutGuide = MAX(navigationBarAreaHeight, layoutAreaHeight);

CGFloat bottomLayoutGuide = rootViewController.view.layoutMargins.bottom;

float magicNumber = 5;//Apple Constant

//

float keyboardHeight = kbSize.height-topLayoutGuide-bottomLayoutGuide+magicNumber;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接