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

时间:2014-09-16 17:26:35

标签: ios objective-c cocoa-touch keyboard ios8

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

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

}

我在模拟器中运行它。

问题是因为iOS 8这不会给出正确的值,如果键盘建议结束或我按下它们会得到不同的(不正确的)值。

如何获得键盘的确切尺寸,包括键盘建议?

10 个答案:

答案 0 :(得分:119)

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

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

  1. 打开 Apple系统键盘时(纵向)
    • UIKeyboardWillShowNotification以键盘高度 224
    • 发送
  2. 打开 Swype键盘时(纵向):
    • UIKeyboardWillShowNotification以键盘高度 0
    • 发送
    • UIKeyboardWillShowNotification的键盘高度为 216
    • UIKeyboardWillShowNotification以键盘高度 256
    • 发送
  3. 打开 SwiftKey键盘时(纵向):
    • UIKeyboardWillShowNotification以键盘高度 0
    • 发送
    • UIKeyboardWillShowNotification的键盘高度为 216
    • UIKeyboardWillShowNotification以键盘高度 259
    • 发送
  4. 为了在一个代码行中正确处理这些场景,您需要:

    针对 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;
    

    实施 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;
    }
    

    注意:您可能希望为视图的偏移设置动画。 info 字典包含由 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;
    }
    

答案 1 :(得分:95)

使用

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

答案 2 :(得分:18)

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

Convert UIKeyboardFrameEndUserInfoKey

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

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

以前,我有一个使用UIKeyboardFrameEndUserInfoKey没有使用convertRect的iPad应用,而且效果很好。

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

现在,对于iOS 8,使用此convertRect功能至关重要。

答案 3 :(得分:7)

与Swift 2.0中编写的dgangsta's解决方案类似:

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
}

答案 4 :(得分:5)

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

您可以这样使用:

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

答案 5 :(得分:4)

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

如果是这样,那么这是一个包容性规范:

enter image description 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)")
}

答案 6 :(得分:0)

我注意到在默认键盘和自定义(# This script heavily relies on the HTML structure of webpages mentioned below # indiabix.com/aptitude/simple-interest, indiabix.com/aptitude/numbers which are similar import sys import urllib.request from docx import Document from bs4 import BeautifulSoup soup = "" para = "" root = "http://www.indiabix.com" def getQuestions(link): req = urllib.request.urlopen(link) soup = BeautifulSoup(req.read(),'html5lib') boxes = soup.find_all('div',{'class':'bix-div-container'}) for box in boxes: headers = box.find("td",{"class":"bix-td-qtxt"}) para = doc.add_paragraph(headers.get_text()) options = box.find_all("td",{'class':'bix-td-option'}) para.text += "\n" for option in options: para.text = para.text + (option.get_text()+" ") return soup def getExtras(soup): main = soup.find('p',{'class':'ib-pager'}).find_all('a') for m in main[:-1]: getQuestions(root+m['href']) return if __name__ == '__main__': # Here, the string "http://indiabix.com/aptitude/numbers" is used as the input link link = input("Enter link : ") doc = Document() soup = getQuestions(link) getExtras(soup) doc.save('questions.docx') )键盘之间切换时出现问题 - 从默认键盘切换后,自定义键盘将显示253高度而不是162。

在这种情况下有用的是使用自定义键盘为输入字段设置UIPickerView

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

答案 7 :(得分:0)

swift只有一个字符串:

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

UIKeyboardFrameEndUserInfoKey始终存储NSValue,因此无需检查。

答案 8 :(得分:0)

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

答案 9 :(得分:0)

[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {

    float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

}];