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

can';无法在iOS8中获得正确的键盘高度值,ios,objective-c,cocoa-touch,keyboard,ios8,Ios,Objective C,Cocoa Touch,Keyboard,Ios8,我使用此代码确定键盘的大小: - (void)keyboardWillChange:(NSNotification *)notification { NSDictionary* keyboardInfo = [notification userInfo]; NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey]; CGRect keyboardFram

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

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

}
我在模拟器里运行这个

问题是,由于iOS 8,这将不会给出正确的值,如果键盘建议向上或向下,则会得到不同(不正确)的值

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

使用

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

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

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

  • 苹果系统键盘打开时(纵向)
    • 发送UIKeyboardWillShowNotification时,键盘高度为224
  • 打开Swype键盘时(纵向):
    • UIKeyboardWillShow通知以0的键盘高度发送
    • UIKeyboardWillShowNotification以216的键盘高度发送
    • UIKeyboardWillShowNotification以256的键盘高度发送
  • 快捷键键盘打开时(纵向):
    • UIKeyboardWillShow通知以0的键盘高度发送
    • UIKeyboardWillShowNotification以216的键盘高度发送
    • 发送UIKeyboardWillShow通知时,键盘高度为259
  • 为了在一个代码行中正确处理这些场景,您需要:

    根据UIKeyboardWillShowNotification和UIKeyboardWillHideNotification通知注册观察员:

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
    
    创建全局变量以跟踪当前键盘高度:

    CGFloat _currentKeyboardHeight = 0.0f;
    
    - (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;
    }
    
    机具键盘将显示以响应当前键盘高度的变化:

    CGFloat _currentKeyboardHeight = 0.0f;
    
    - (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;
    }
    
    注意:您可能希望设置视图偏移的动画。信息字典包含由UIKeyboardAnimationDurationUserInfoKey键入的值。此值可用于以与显示键盘相同的速度设置更改的动画

    机具键盘将隐藏到重置_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文章:

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

    NSDictionary* d = [notification userInfo];
    CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    r = [myView convertRect:r fromView:nil];
    
    以前,我有一个iPad应用程序,它使用了
    UIKeyboardFrameEndUserInfoKey
    ,但没有使用
    convertRect
    ,而且运行良好

    但在iOS 8中,它不再正常工作。突然,它报告说我的键盘在iPad上以横向模式运行,高1024像素

    现在,在iOS 8中,您必须使用此
    convertRect
    功能。

    类似于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
    }
    

    我为
    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
            )
        }
    }
    

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

    在这种情况下,有效的方法是设置
    autocorrectionType=UITextAutocorrectionTypeNo


    该问题仅在iOS 8中出现(仅在模拟器上测试)。它不会出现在iOS 9(模拟器或设备)中。

    swift只有一个字符串:

    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...
            }
        })
    

    有些时候,开发者需要在实际显示键盘高度之前知道它,从而允许他们适当地预先布局界面

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

    这包括顶部的快速类型栏,因为在所有当前版本的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)")
    }
    

    如果您将
    keyboardFrameBeginRect
    转换为本地坐标,可能会有所帮助。@rmaddy这并不重要,我只需要高度。根据方向不同,这可能是错误的。尽管这在iOS 8下可能不再是一个问题。试试看,看是否有什么不同。@rmaddy我试过了,但遗憾的是,它并没有帮助我找到好答案。谢谢你是怎么发现你应该用那把钥匙的@SouvickSecgrect keyboardFrame=[keyboardFrameBegin CGRectValue];我没用,键盘还是258,太高了谢谢@trycatch今天终于上了一课。UIKeyboardFrameEndUserInfoKey和UIKeyboardFrameBeginUserInfoKey有很大区别。谢谢@souviccsedgangsta,您的研究很有趣,但问题的关键在于获取FrameBegin而不是FrameEnd属性。根据您的回答,您是否考虑过使用UIVIEW ItValtuoPosixOrgCurrnType标记到视图动画方法而不是Deltas?而对于SWIFFTKEY(V1.2.3)高度,259是iOffe6+,271是iOS81.3,它仍然是一个工作解决方案吗?使用快捷键时,我得到的高度是44,而不是259。疯狂的是,这对我很有帮助,但在键盘已经显示出来后,我需要键盘的高度,所以我观察键盘显示:取而代之。为什么这些定制键盘会触发3次通知,而苹果的键盘只会触发一次?似乎不一致。如果你像我一样在横向模式下使用iPhone时遇到问题,那是因为帧结束键的来源错误(至少对于普通的iOS 10键盘而言)<代码>键盘开始矩形:(0.0375.0667.01262.0)。。。键盘末端矩形:(0.0213.0667.01262.0)
    iOS8之前的键盘矩形始终在纵向屏幕坐标中。我添加了代码,在横向模式下手动交换高度和宽度,但是