在iOS8中无法获得正确的键盘高度值

我正在使用这段代码来确定键盘的大小:

- (void)keyboardWillChange:(NSNotification *)notification { NSDictionary* keyboardInfo = [notification userInfo]; NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey]; CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue]; } 

我正在模拟器中运行。

问题是,因为iOS 8这不会给出正确的价值,如果键盘的build议起来,或者如果我把它们推下来,我得到不同的(不正确的)值。

我怎样才能得到键盘的确切大小,包括键盘的build议?

使用

 NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey]; 

随着在iOS中引入自定义键盘,这个问题变得更加复杂。

简而言之, UIKeyboardWillShowNotification可以通过自定义键盘实现多次调用:

  1. Apple系统键盘打开时(纵向)
    • UIKeyboardWillShowNotification将以224的键盘高度发送
  2. Swype键盘打开时(纵向):
    • UIKeyboardWillShowNotification以键盘高度0发送
    • 用键盘高度216发送UIKeyboardWillShowNotification
    • UIKeyboardWillShowNotification以256的键盘高度发送
  3. SwiftKey键盘打开时(纵向):
    • UIKeyboardWillShowNotification以键盘高度0发送
    • 用键盘高度216发送UIKeyboardWillShowNotification
    • UIKeyboardWillShowNotification将以259的键盘高度发送

为了在一个代码行中正确处理这些场景,您需要:

UIKeyboardWillShowNotificationUIKeyboardWillHideNotification通知注册观察者:

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

创build一个全局variables来跟踪当前的键盘高度:

 CGFloat _currentKeyboardHeight = 0.0f; 

实现keyboardWillShow对当前键盘高度的变化做出反应:

 - (void)keyboardWillShow:(NSNotification*)notification { NSDictionary *info = [notification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; CGFloat deltaHeight = kbSize.height - _currentKeyboardHeight; // Write code to adjust views accordingly using deltaHeight _currentKeyboardHeight = kbSize.height; } 

注:您可能希望animation的意见偏移。 info字典包含由UIKeyboardAnimationDurationUserInfoKey键入的值。 此值可用于以与显示的键盘相同的速度animation您的更改。

keyboardWillHide实现为reset _currentKeyboardHeight,并对被解散的键盘做出反应:

 - (void)keyboardWillHide:(NSNotification*)notification { NSDictionary *info = [notification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; // Write code to adjust views accordingly using kbSize.height _currentKeyboardHeight = 0.0f; } 

我也有这个问题,直到我遇到这个StackOverflow文章:

转换UIKeyboardFrameEndUserInfoKey

这将向您展示如何使用convertRect函数将键盘的大小转换为可用的值,但在屏幕方向上。

 NSDictionary* d = [notification userInfo]; CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue]; r = [myView convertRect:r fromView:nil]; 

以前,我有一个使用UIKeyboardFrameEndUserInfoKey的iPad应用程序,但没有使用convertRect ,它工作正常。

但是对于iOS 8,它不能正常工作。 突然,它会报告说,我的键盘,运行在横向模式的iPad,是1024像素高

所以现在,在iOS 8中,使用这个convertRect函数是非常重要的。

类似于用Swift 2.0编写的dangsta的解决scheme:

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil) } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardWillShow(notification: NSNotification) { guard let kbSizeValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return } animateToKeyboardHeight(kbSizeValue.CGRectValue().height, duration: kbDurationNumber.doubleValue) } func keyboardWillHide(notification: NSNotification) { guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return } animateToKeyboardHeight(0, duration: kbDurationNumber.doubleValue) } func animateToKeyboardHeight(kbHeight: CGFloat, duration: Double) { // your custom code here } 

我对UIViewController进行了extension

 extension UIViewController { func keyboardWillChangeFrameNotification(notification: NSNotification, scrollBottomConstant: NSLayoutConstraint) { let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber let keyboardBeginFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue() let keyboardEndFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue() let screenHeight = UIScreen.mainScreen().bounds.height let isBeginOrEnd = keyboardBeginFrame.origin.y == screenHeight || keyboardEndFrame.origin.y == screenHeight let heightOffset = keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y - (isBeginOrEnd ? bottomLayoutGuide.length : 0) UIView.animateWithDuration(duration.doubleValue, delay: 0, options: UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16)), animations: { () in scrollBottomConstant.constant = scrollBottomConstant.constant + heightOffset self.view.layoutIfNeeded() }, completion: nil ) } } 

你可以这样使用:

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChangeFrameNotification:", name: UIKeyboardWillChangeFrameNotification, object: nil) } ... deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardWillChangeFrameNotification(notification: NSNotification) { self.keyboardWillChangeFrameNotification(notification, scrollBottomConstant: inputContainerBottom) // Write more to here if you want. } 

有些时候,开发人员在实际显示之前需要知道键盘高度,以便适当地预先布置界面。

如果是这样的话,这里是一个包容的规格:

在这里输入图像描述

这包括在顶部的快速types栏,因为默认情况下在所有当前版本的iOS中。

这里是我用来testing这个的swift 3通知设置,如果有人需要的话:

 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil) } func keyboardWillShow(notification: NSNotification) { guard let keyboardSize = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return } print("\(keyboardSize)") } 

我注意到在默认键盘和自定义( UIPickerView )键盘之间切换时显示的问题 – 在从默认键盘切换之后,自定义键盘将显示253高度而不是162。

在这种情况下工作是设置autocorrectionType = UITextAutocorrectionTypeNo; 用于自定义键盘的input字段。

这个问题只发生在iOS 8(仅在模拟器上testing)。 它不会发生在iOS 9(模拟器或设备)。

只有一个string为快速:

 let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size 

UIKeyboardFrameEndUserInfoKey总是存储NSValue ,所以不需要检查。

在Swift中,不在一行中

 self.keyboardDidShowObserver = NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { (notification) in if let userInfo = notification.userInfo, let keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue { let keyboardRect = keyboardFrameValue.CGRectValue() // keyboardRect.height gives the height of the keyboard // your additional code here... } }) 
 [notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) { float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; }];