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

Eli*_*kiy 81 keyboard cocoa-touch objective-c ios ios8

我使用此代码来确定键盘的大小:

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

}
Run Code Online (Sandbox Code Playgroud)

我在模拟器中运行它.

问题是,因为iOS 8这将不会给出正确的值,如果键盘建议已启动或者如果我将它们向下推,则会得到不同的(不正确的)值.

如何获得键盘的确切大小,包括键盘建议?

小智 120

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

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

  1. 苹果的系统键盘被打开(纵向)
    • 发送UIKeyboardWillShowNotification时键盘高度为224
  2. 了Swype键盘被打开(纵向):
    • 发送UIKeyboardWillShowNotification时键盘高度为0
    • 发送UIKeyboardWillShowNotification时键盘高度为216
    • 发送UIKeyboardWillShowNotification时键盘高度为256
  3. SwiftKey键盘被打开(纵向):
    • 发送UIKeyboardWillShowNotification时键盘高度为0
    • 发送UIKeyboardWillShowNotification时键盘高度为216
    • 发送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];
Run Code Online (Sandbox Code Playgroud)

创建一个全局变量来跟踪当前键盘高度:

CGFloat _currentKeyboardHeight = 0.0f;
Run Code Online (Sandbox Code Playgroud)

实现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;
}
Run Code Online (Sandbox Code Playgroud)

注意:您可能希望为视图的偏移设置动画.该信息字典包含键的值UIKeyboardAnimationDurationUserInfoKey.此值可用于以与显示的键盘相同的速度为更改设置动画.

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 它仍然是一个有效的解决方案?当使用SwiftKey时,我的高度为44而不是259. (2认同)

sou*_*cse 95

使用

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
Run Code Online (Sandbox Code Playgroud)

  • 对我不起作用,键盘仍然是258,太高了 (12认同)
  • CGRect keyboardFrame = [keyboardFrameBegin CGRectValue]; (6认同)

Mik*_*ill 18

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

转换UIKeyboardFrameEndUserInfoKey

这将向您展示如何使用该convertRect功能,将键盘的大小转换为可用的,但在屏幕方向上.

NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];
Run Code Online (Sandbox Code Playgroud)

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

但是对于iOS 8,它已经不再适用了.突然间,它会报告我在横向模式下在iPad上运行的键盘高度1024像素.

所以现在,使用iOS 8,您必须使用此convertRect功能.


Avt*_*Avt 7

类似于用Swift 2.0编写的dgangsta解决方案:

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
}
Run Code Online (Sandbox Code Playgroud)


Wan*_*hoi 5

extensionUIViewController

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
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以这样使用:

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.
}
Run Code Online (Sandbox Code Playgroud)


Tra*_* M. 5

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

如果是这种情况,这里有一个包容性规范:

在此处输入图片说明

这包括顶部的快速输入栏,因为它在所有当前版本的 iOS 中默认处于打开状态。

这是我用来测试的 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)")
}
Run Code Online (Sandbox Code Playgroud)