138

The height of a keyboard on varying iOS devices is different. Does anybody know how I can get height of a device's keyboard programmatically?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Lachtan
  • 4,803
  • 6
  • 28
  • 34
  • 1
    Possible duplicate of http://stackoverflow.com/questions/11284321/what-is-the-height-of-iphones-onscreen-keyboard – Kendel Aug 02 '15 at 16:33

13 Answers13

273

Swift

You can get the keyboard height by subscribing to the UIKeyboardWillShowNotification notification. (Assuming you want to know what the height will be before it's shown).

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

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
    }
אורי orihpt
  • 2,358
  • 2
  • 16
  • 41
roc
  • 2,829
  • 1
  • 11
  • 6
  • I don't understand why the guy here http://www.think-in-g.net/ghawk/blog/2012/09/practicing-auto-layout-an-example-of-keyboard-sensitive-layout/ checks for isPortrait. Won't keyboardRectangle.height be still correct in all orientations? – Anton Tropashko Aug 30 '16 at 09:08
  • 5
    yes, in swift 3 its messed. giving different value every time – Mahesh Agrawal Mar 21 '17 at 05:37
  • NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil) is the right syntax – shinyuX Jun 06 '17 at 15:48
  • 1
    What if you already have the keyboard visible, and you rotate the device, how do you find the new keyboard height? – Khoury Mar 28 '18 at 03:03
  • 1
    Use this for **Swift 4**: `UIResponder.keyboardWillShowNotification` in the name bit – George Jul 12 '18 at 17:48
  • How can I access the keyboardHeight variable in viewDidLoad()? I tried reassigning it using something like KBHeight = Int(keyboardHeight). – M Waz Apr 29 '19 at 19:41
  • It doesn't work with the keyboard without the toolbar! (for example, if selected Ukrainian language) – IvanPavliuk May 04 '19 at 09:52
  • Why is the dict value being cast as an NSValue? You should update this, it should be cast as CGRect like: (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height – Joshua Hart Jun 13 '20 at 03:15
64

Swift 3.0 and Swift 4.1

1- Register the notification in the viewWillAppear method:

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

2- Method to be called:

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardHeight = keyboardSize.height
        print(keyboardHeight)
    }
}
Community
  • 1
  • 1
fs_tigre
  • 10,650
  • 13
  • 73
  • 146
  • 3
    This works, you can also have the `keyboardWillShow` parameter be of type `Notification` to make this more Swift 3.0 compliant. – bfich Oct 31 '16 at 18:47
  • 1
    when we call the function keyBoardWillShow(), what exactly do we put as the argument? I have added the first line in viewDidLoad, and the function in the class... but I'm not sure how to call it haha – VDog Feb 21 '17 at 07:46
  • 1
    @VDog you don't call it, iOS will call it when the keyboard is shown – Jeremiah Nunn Apr 07 '17 at 23:27
  • 4
    Registering for the notification in `viewDidLoad` is not a good idea: where do you put the matching `removeObserver` call so that when this VC is no longer being shown, it stops getting notifications? It is better to put the registration for notifications in `viewWillAppear`, and then put the `removeObserver` call in `viewWillDisappear` – xaphod Apr 25 '17 at 15:06
  • @xaphod you right, `viewWillAppear` seem to be a better place to register notifications, I will update my post. Removing the observer in no longer necessary unless you are supporting older versions (>= iOS8). Thanks. Apple Docs: https://developer.apple.com/library/content/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter – fs_tigre Apr 26 '17 at 12:20
  • 6
    You need to change "UIKeyboardFrameBeginUserInfoKey" to "UIKeyboardFrameEndUserInfoKey" because in your example you often can get zero height. The details: https://stackoverflow.com/questions/45689664/ios-11-keyboard-height-is-returning-0-in-keyboard-notification – andreylanadelrey Nov 10 '17 at 14:28
  • I tested the original key 'UIKeyboardFrameBeginUserInfoKey' and it did not always provide the correct value. Then changed to 'UIKeyboardFrameEndUserInfoKey' per @andreylanadelrey's comment and it fixed the issue. Updated answer text to use the new key. – Andres Canella Apr 10 '18 at 21:12
34

Swift 4 and Constraints

To your tableview add a bottom constraint relative to the bottom safe area. In my case the constraint is called 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
}
Eduardo Irias
  • 1,043
  • 11
  • 12
21

Update Swift 4.2

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

selector method:

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

extension:

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

Update Swift 3.0

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

selector method:

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

extension:

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

Tip

UIKeyboardDidShowNotification or UIKeyboardWillShowNotification might called twice and got different result, this article explained why called twice.

In Swift 2.2

Swift 2.2 deprecates using strings for selectors and instead introduces new syntax: #selector.

Something like:

private func setUpObserver() {

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

selector method:

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

extension:

    private extension Selector {

    static let keyboardWillShow = #selector(YourViewController.keyboardWillShow(_:)) 
}
Jesse
  • 466
  • 1
  • 5
  • 13
  • 3
    Don't forget to remove the observer in deinit, e.g.: NSNotificationCenter.defaultCenter().removeObserver(self) – tapmonkey Sep 18 '16 at 10:52
16

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)")
            }
        }
    }
Community
  • 1
  • 1
Vivek
  • 4,916
  • 35
  • 40
11

Shorter version here:

func keyboardWillShow(notification: NSNotification) {

        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            let keyboardHeight = keyboardSize.height
        }
}
LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174
Alessign
  • 768
  • 9
  • 17
  • 1
    what argument do you pass for keyboardWillShow under notification? – VDog Feb 21 '17 at 07:46
  • Hard to tell, I was replying to the code block of the poster...but it corresponds with this line (let userInfo:NSDictionary = notification.userInfo!) – Alessign Apr 26 '17 at 09:29
6

Swift 4 .

Simplest Method

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

}
ZAFAR007
  • 3,049
  • 1
  • 34
  • 45
3

Objective-C version:

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

and then:

- (void)keyboardWillShow:(NSNotification *)notification
{
CGFloat height = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
}
oskarko
  • 3,382
  • 1
  • 26
  • 26
2

// Step 1 :- Register 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)
}

// Step 2 :- These Methods will be called Automatically when Keyboard appears Or Hides

    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
    }
Nrv
  • 280
  • 1
  • 6
1

The method by ZAFAR007 updated for Swift 5 in Xcode 10

override func viewDidLoad() {
    super.viewDidLoad()

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

}




@objc func keyboardWillShow(notification: NSNotification) {

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

}
P.T.Dog94
  • 17
  • 2
1

I uses below code,

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
}
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
0

I had to do this. this is a bit of hackery. not suggested.
but i found this very helpful

I made extension and struct

ViewController Extension + Struct

import UIKit
struct viewGlobal{
    static var bottomConstraint : NSLayoutConstraint = NSLayoutConstraint()
}

extension UIViewController{ //keyboardHandler
 func hideKeyboardWhenTappedAround() {
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    tap.cancelsTouchesInView = false
    view.addGestureRecognizer(tap)
 }
 func listenerKeyboard(bottomConstraint: NSLayoutConstraint) {
    viewGlobal.bottomConstraint = bottomConstraint
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    // Register your Notification, To know When Key Board Hides.
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
 }
 //Dismiss Keyboard
 @objc func dismissKeyboard() {
    view.endEditing(true)
 }
 @objc func keyboardWillShow(notification:NSNotification) {
    let userInfo:NSDictionary = notification.userInfo! as NSDictionary
    let keyboardFrame:NSValue = userInfo.value(forKey: UIResponder.keyboardFrameEndUserInfoKey) as! NSValue
    let keyboardRectangle = keyboardFrame.cgRectValue
    let keyboardHeight = keyboardRectangle.height
    UIView.animate(withDuration: 0.5){
        viewGlobal.bottomConstraint.constant = keyboardHeight
    }
 }

 @objc func keyboardWillHide(notification:NSNotification) {
    UIView.animate(withDuration: 0.5){
        viewGlobal.bottomConstraint.constant = 0
    }
 }
}

Usage:
get most bottom constraint

@IBOutlet weak var bottomConstraint: NSLayoutConstraint! // default 0

call the function inside viewDidLoad()

override func viewDidLoad() {
    super.viewDidLoad()

    hideKeyboardWhenTappedAround()
    listenerKeyboard(bottomConstraint: bottomConstraint)

    // Do any additional setup after loading the view.
}

Hope this help.
-you keyboard will now auto close when user tap outside of textfield and
-it will push all view to above keyboard when keyboard appear.
-you could also used dismissKeyboard() when ever you need it

Muhammad Asyraf
  • 1,748
  • 15
  • 20
-1

if let keyboardSize = (sender.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { let keyboardHeight = keyboardSize.height print(keyboardHeight) }

  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 08 '22 at 17:17