如何获取键盘的高度?

139

在不同的iOS设备上,键盘的高度不同。有人知道我如何通过编程来获取设备键盘的高度吗?


1
可能是 https://dev59.com/O2gu5IYBdhLWcg3wfHI_ 的重复问题。 - Kendel
13个回答

276

Swift

如果你想在键盘弹出之前知道它的高度,你可以订阅UIKeyboardWillShowNotification通知来获取。

Swift 4

NotificationCenter.default.addObserver(
    self,
    selector: #selector(keyboardWillShow),
    name: UIResponder.keyboardWillShowNotification,
    object: nil
)
@objc func keyboardWillShow(_ notification: Notification) {
    if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height
    }
}

Swift 3

NotificationCenter.default.addObserver(
    self,
    selector: #selector(keyboardWillShow),
    name: NSNotification.Name.UIKeyboardWillShow,
    object: nil
)
@objc func keyboardWillShow(_ notification: Notification) {
    if let keyboardFrame: NSValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height
    }
}

Swift 2

->

Swift 2

NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
func keyboardWillShow(notification: NSNotification) {
        let userInfo: NSDictionary = notification.userInfo!
        let keyboardFrame: NSValue = userInfo.valueForKey(UIKeyboardFrameEndUserInfoKey) as! NSValue
        let keyboardRectangle = keyboardFrame.CGRectValue()
        let keyboardHeight = keyboardRectangle.height
    }

我不明白为什么这个人在这里 http://www.think-in-g.net/ghawk/blog/2012/09/practicing-auto-layout-an-example-of-keyboard-sensitive-layout/ 检查isPortrait。在所有方向上,keyboardRectangle.height不都是正确的吗? - Anton Tropashko
5
是的,在Swift 3中这很混乱。每次都会给出不同的值。 - Mahesh Agrawal
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil) 是正确的语法。 - shinyuX
1
如果您已经打开了键盘,并且旋转设备,那么如何找到新的键盘高度? - Khoury
1
在Swift 4中使用以下代码:UIResponder.keyboardWillShowNotification来获取键盘即将显示的通知。 - George
显示剩余3条评论

64

Swift 3.0 和 Swift 4.1

1- 在 viewWillAppear 方法中注册通知:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)

2- 要调用的方法:

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardHeight = keyboardSize.height
        print(keyboardHeight)
    }
}

3
这个可以用Notification类型的keyboardWillShow参数,使其更符合Swift 3.0标准。 - bfich
1
当我们调用函数keyBoardWillShow()时,我们应该将什么作为参数传递呢?我已经在viewDidLoad中添加了第一行代码,并在类中定义了该函数...但是我不确定如何调用它哈哈。 - VDog
1
@VDog 你不需要调用它,当键盘显示时,iOS会自动调用它。 - Jeremiah Nunn
4
viewDidLoad中注册通知不是一个好主意:如果这个视图控制器不再显示,你该在哪里放置匹配的removeObserver调用以停止接收通知?更好的方法是在viewWillAppear中注册通知,然后将removeObserver调用放在viewWillDisappear中。 - xaphod
6
由于你的示例经常返回零高度,因此需要将“UIKeyboardFrameBeginUserInfoKey”更改为“UIKeyboardFrameEndUserInfoKey”。详情请参见:https://dev59.com/HVcO5IYBdhLWcg3whR7M - andreylanadelrey
显示剩余2条评论

34

Swift 4 和约束

为您的表格视图添加一个相对于底部安全区域的底部约束。在我的情况下,该约束被称为 tableViewBottomLayoutConstraint。

@IBOutlet weak var tableViewBottomLayoutConstraint: NSLayoutConstraint!

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(notification:)), name: .UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(notification:)), name: .UIKeyboardWillHide, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow , object: nil)
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide , object: nil)
}

@objc 
func keyboardWillAppear(notification: NSNotification?) {

    guard let keyboardFrame = notification?.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
        return
    }

    let keyboardHeight: CGFloat
    if #available(iOS 11.0, *) {
        keyboardHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
    } else {
        keyboardHeight = keyboardFrame.cgRectValue.height
    }

    tableViewBottomLayoutConstraint.constant = keyboardHeight
}

@objc 
func keyboardWillDisappear(notification: NSNotification?) {
    tableViewBottomLayoutConstraint.constant = 0.0
}

3
针对任何一个问题的第一个回答需要考虑到安全区域。谢谢! - Zachary Nicoll

21

更新Swift 4.2

private func setUpObserver() {
    NotificationCenter.default.addObserver(self, selector: .keyboardWillShow, name: UIResponder.keyboardWillShowNotification, object: nil)
}

选择器方法:

@objc fileprivate func keyboardWillShow(notification:NSNotification) {
    if let keyboardRectValue = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardHeight = keyboardRectValue.height
    }
}

扩展:

private extension Selector {
    static let keyboardWillShow = #selector(YourViewController.keyboardWillShow(notification:)) 
}

更新Swift 3.0

private func setUpObserver() {
    NotificationCenter.default.addObserver(self, selector: .keyboardWillShow, name: .UIKeyboardWillShow, object: nil)
}

选择器方法:

@objc fileprivate func keyboardWillShow(notification:NSNotification) {
    if let keyboardRectValue = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardHeight = keyboardRectValue.height
    }
}

扩展:

private extension Selector {
    static let keyboardWillShow = #selector(YourViewController.keyboardWillShow(notification:)) 
}

提示

UIKeyboardDidShowNotification或UIKeyboardWillShowNotification可能会被调用两次,并得到不同的结果,这篇文章解释了为什么会被调用两次。

在Swift 2.2中

Swift 2.2弃用使用字符串作为选择器,并引入新的语法:#selector

类似于:

private func setUpObserver() {

    NSNotificationCenter.defaultCenter().addObserver(self, selector: .keyboardWillShow, name: UIKeyboardWillShowNotification, object: nil)
}

选择器方法:

@objc private func keyboardWillShow(notification:NSNotification) {

    let userInfo:NSDictionary = notification.userInfo!
    let keyboardFrame:NSValue = userInfo.valueForKey(UIKeyboardFrameEndUserInfoKey) as! NSValue
    let keyboardRectangle = keyboardFrame.CGRectValue()
    let keyboardHeight = keyboardRectangle.height
    editorBottomCT.constant = keyboardHeight
}

扩展:

    private extension Selector {

    static let keyboardWillShow = #selector(YourViewController.keyboardWillShow(_:)) 
}

3
别忘了在析构函数中移除观察者,例如:NSNotificationCenter.defaultCenter().removeObserver(self)。 - tapmonkey

17

Swift 5

override func viewDidLoad() {
    //  Registering for keyboard notification.
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
}


/*  UIKeyboardWillShowNotification. */
    @objc internal func keyboardWillShow(_ notification : Notification?) -> Void {
        
        var _kbSize:CGSize!
        
        if let info = notification?.userInfo {

            let frameEndUserInfoKey = UIResponder.keyboardFrameEndUserInfoKey
            
            //  Getting UIKeyboardSize.
            if let kbFrame = info[frameEndUserInfoKey] as? CGRect {
                
                let screenSize = UIScreen.main.bounds
                
                //Calculating actual keyboard displayed size, keyboard frame may be different when hardware keyboard is attached (Bug ID: #469) (Bug ID: #381)
                let intersectRect = kbFrame.intersection(screenSize)
                
                if intersectRect.isNull {
                    _kbSize = CGSize(width: screenSize.size.width, height: 0)
                } else {
                    _kbSize = intersectRect.size
                }
                print("Your Keyboard Size \(_kbSize)")
            }
        }
    }

3
这是一个非常好的答案。当软键盘被隐藏时,这个结果是正确的。 - DevGom

11

这里有一个更短的版本:

func keyboardWillShow(notification: NSNotification) {

        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            let keyboardHeight = keyboardSize.height
        }
}

1
在通知中,你为keyboardWillShow传递什么参数? - VDog
很难说,我是在回复帖子的代码块...但它对应着这一行代码(let userInfo:NSDictionary = notification.userInfo!)。 - Alessign

6

Swift 4

最简单的方法

override func viewDidLoad() {
      super.viewDidLoad()
      NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
}

func keyboardWillShow(notification: NSNotification) {  

      if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
             let keyboardHeight : Int = Int(keyboardSize.height)
             print("keyboardHeight",keyboardHeight) 
      }

}

3

Objective-C 版本:

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

接下来:

- (void)keyboardWillShow:(NSNotification *)notification
{
CGFloat height = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
}

2

// 步骤1:注册NotificationCenter

ViewDidLoad() {

   self.yourtextfield.becomefirstresponder()

   // Register your Notification, To know When Key Board Appears.
    NotificationCenter.default.addObserver(self, selector: #selector(SelectVendorViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

   // Register your Notification, To know When Key Board Hides.
    NotificationCenter.default.addObserver(self, selector: #selector(SelectVendorViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

// 第二步: 当键盘出现或隐藏时,这些方法将自动调用

    func keyboardWillShow(notification:NSNotification) {
        let userInfo:NSDictionary = notification.userInfo! as NSDictionary
        let keyboardFrame:NSValue = userInfo.value(forKey: UIKeyboardFrameEndUserInfoKey) as! NSValue
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height
        tblViewListData.frame.size.height = fltTblHeight-keyboardHeight
    }

    func keyboardWillHide(notification:NSNotification) {
        tblViewListData.frame.size.height = fltTblHeight
    }

1

我使用以下代码:

override func viewDidLoad() {
    super.viewDidLoad()
    self.registerObservers()
}

func registerObservers(){

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

@objc func keyboardWillAppear(notification: Notification){
    if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height
        self.view.transform = CGAffineTransform(translationX: 0, y: -keyboardHeight)
    }
}

@objc func keyboardWillHide(notification: Notification){
        self.view.transform = .identity
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接