ios 无法在 iOS8 中获得正确的键盘高度值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/25874975/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
can't get correct value of keyboard height in iOS8
提问by Eli Braginskiy
I was using this code to determine what is the size of the keyboard :
我正在使用此代码来确定键盘的大小:
- (void)keyboardWillChange:(NSNotification *)notification {
    NSDictionary* keyboardInfo = [notification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
}
I'm running this in the simulator.
我在模拟器中运行它。
The problem is since iOS 8 this will not give the correct value, if the keyboard suggestions is up or if I push them down I get different (not correct) values.
问题是因为 iOS 8 这不会给出正确的值,如果键盘建议是向上的,或者如果我按下它们,我会得到不同的(不正确的)值。
How can I get the exact size of the keyboard including the keyboard suggestions?
如何获得键盘的确切尺寸,包括键盘建议?
回答by dgangsta
With the introduction of custom keyboards in iOS, this problem becomes a tad more complex.
随着 iOS 中自定义键盘的引入,这个问题变得有点复杂。
In short, the UIKeyboardWillShowNotificationcan get called multiple times by custom keyboard implementations:
简而言之,自定义键盘实现可以多次调用UIKeyboardWillShowNotification:
- When the Apple systemkeyboard is opened (in portrait)
- UIKeyboardWillShowNotification is sent with a keyboard height of 224
 
- When the Swype keyboardis opened (in portrait):
- UIKeyboardWillShowNotification is sent with a keyboard height of 0
- UIKeyboardWillShowNotification is sent with a keyboard height of 216
- UIKeyboardWillShowNotification is sent with a keyboard height of 256
 
- When the SwiftKey keyboardis opened (in portrait):
- UIKeyboardWillShowNotification is sent with a keyboard height of 0
- UIKeyboardWillShowNotification is sent with a keyboard height of 216
- UIKeyboardWillShowNotification is sent with a keyboard height of 259
 
- 当Apple 系统键盘打开时(纵向)
- UIKeyboardWillShowNotification 发送时键盘高度为224
 
- 当Swype 键盘打开时(纵向):
- UIKeyboardWillShowNotification 发送时键盘高度为0
- UIKeyboardWillShowNotification 发送时键盘高度为216
- UIKeyboardWillShowNotification 发送时键盘高度为256
 
- 当SwiftKey 键盘打开时(纵向):
- UIKeyboardWillShowNotification 发送时键盘高度为0
- UIKeyboardWillShowNotification 发送时键盘高度为216
- UIKeyboardWillShowNotification 发送时键盘高度为259
 
In order to handle these scenarios properly in one code-line, you need to:
为了在一个代码行中正确处理这些场景,您需要:
Register observers against the UIKeyboardWillShowNotificationand UIKeyboardWillHideNotificationnotifications:
针对UIKeyboardWillShowNotification和UIKeyboardWillHideNotification通知注册观察者:
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];    
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
Create a global variable to track the current keyboard height:
创建一个全局变量来跟踪当前的键盘高度:
CGFloat _currentKeyboardHeight = 0.0f;
Implement keyboardWillShowto react to the current change in keyboard height:
实现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;
}
NOTE: You may wish to animate the offsetting of views. The infodictionary contains a value keyed by UIKeyboardAnimationDurationUserInfoKey. This value can be used to animate your changes at the same speed as the keyboard being displayed.
注意:您可能希望为视图偏移设置动画。该信息字典包含键的值UIKeyboardAnimationDurationUserInfoKey。此值可用于以与显示键盘相同的速度为您的更改设置动画。
Implement keyboardWillHideto the reset _currentKeyboardHeight and react to the keyboard being dismissed:
将keyboardWillHide实现为重置的 _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;
}
回答by souvickcse
Use
用
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
回答by Mike Gledhill
I also had this issue, until I came across this StackOverflowarticle:
我也有这个问题,直到我遇到这篇StackOverflow文章:
Convert UIKeyboardFrameEndUserInfoKey
转换 UIKeyboardFrameEndUserInfoKey
This shows you how to use the convertRectfunction, to convert the keyboard's size into something usable, but on the screen orientation.
这将向您展示如何使用该convertRect功能,将键盘的大小转换为可用的大小,但在屏幕方向上。
NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];
Previously, I had an iPad app which used UIKeyboardFrameEndUserInfoKeybut didn'tuse convertRect, and it worked fine.
以前,我有一个 iPad 应用程序,它使用UIKeyboardFrameEndUserInfoKey但没有使用convertRect,并且运行良好。
But with iOS 8, it no longer worked properly. Suddenly, it would report that my keyboard, running on an iPad in landscape mode, was 1024 pixels high.
但是在 iOS 8 中,它不再正常工作。突然,它会报告我的键盘在 iPad 上以横向模式运行,高度为1024 像素。
So now, with iOS 8, it's essential that you use this convertRectfunction.
所以现在,在 iOS 8 中,使用这个convertRect功能是必不可少的。
回答by Avt
The similar to dgangsta'ssolution written in Swift 2.0:
类似于dgangsta用 Swift 2.0 编写的解决方案:
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
}
回答by Wanbok Choi
I make extensionfor UIViewController
我extension为UIViewController
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
        )
    }
}
You can use like this :
你可以这样使用:
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.
}
回答by Travis M.
There are times when devs need to know the keyboard height before it's actually shown, allowing them pre-layout the interface appropriately.
有时开发人员需要在实际显示之前知道键盘高度,以便他们适当地预先布局界面。
If that's the case, here's an inclusive spec:
如果是这种情况,这里有一个包容性规范:
This includes the quick type bar at the top, since that is on by default in all current versions of iOS.
这包括顶部的快速输入栏,因为它在所有当前版本的 iOS 中默认处于打开状态。
Here is the swift 3 notification setup I used to test this, if anyone needs it:
这是我用来测试的 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)")
}
回答by Petr Syrov
Only one string for swift:
swift 只有一个字符串:
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size
UIKeyboardFrameEndUserInfoKeyalways stores NSValue, so no need to check it.
UIKeyboardFrameEndUserInfoKey总是存储NSValue,所以不需要检查它。
回答by Murray Sagal
In Swift, not in one line...
在 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...
        }
    })
回答by Leo Cavalcante
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {
    float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
}];
回答by alex-i
I noticed an issue showing when switching between default keyboard and a custom (UIPickerView) keyboard - the custom keyboard would show a 253 height instead of 162, after switching from the default keyboard.  
我注意到在默认键盘和自定义 ( UIPickerView) 键盘之间切换时出现的问题- 从默认键盘切换后,自定义键盘将显示 253 高度而不是 162。  
What worked in this case was setting autocorrectionType = UITextAutocorrectionTypeNo;for the input field with the custom keyboard.  
在这种情况下autocorrectionType = UITextAutocorrectionTypeNo;,使用自定义键盘设置输入字段是有效的。  
The issue only occured in iOS 8 (tested on simulator only). It doesn't occur in iOS 9 (simulator or device).
该问题仅在 iOS 8 中出现(仅在模拟器上测试)。它不会发生在 iOS 9(模拟器或设备)中。


