can't get correct value of keyboard height in iOS8
With the introduction of custom keyboards in iOS, this problem becomes a tad more complex.
In short, the UIKeyboardWillShowNotification can get called multiple times by custom keyboard implementations:
- When the Apple system keyboard is opened (in portrait)
- UIKeyboardWillShowNotification is sent with a keyboard height of 224
- When the Swype keyboard is 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 keyboard is 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
In order to handle these scenarios properly in one code-line, you need to:
Register observers against the UIKeyboardWillShowNotification and UIKeyboardWillHideNotification notifications:
[[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 keyboardWillShow to react to the current change in keyboard height:
- (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 info dictionary contains a value keyed by UIKeyboardAnimationDurationUserInfoKey. This value can be used to animate your changes at the same speed as the keyboard being displayed.
Implement keyboardWillHide to the reset _currentKeyboardHeight and react to the keyboard being dismissed:
- (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;}
Use
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
I also had this issue, until I came across this StackOverflow article:
Convert UIKeyboardFrameEndUserInfoKey
This shows you how to use the convertRect
function, to convert the keyboard's size into something usable, but on the screen orientation.
NSDictionary* d = [notification userInfo];CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];r = [myView convertRect:r fromView:nil];
Previously, I had an iPad app which used UIKeyboardFrameEndUserInfoKey
but didn't use convertRect
, and it worked fine.
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.
So now, with iOS 8, it's essential that you use this convertRect
function.