When the system shows or hides the
keyboard, it posts several keyboard
notifications. These notifications
contain information about the
keyboard, including its size, which
you can use for calculations that
involve moving views. Registering for
these notifications is the only way to
get some types of information about
the keyboard. The system delivers the
following notifications for
keyboard-related events:
For more information about these
notifications, see their descriptions
in UIWindow Class Reference. For
information about how to show and hide
the keyboard, see Text and Web.
Create a UIKeyboardListener when you know the keyboard is not visible, for example by calling [UIKeyboardListener shared] from applicationDidFinishLaunching.
When you enter a textField, it becomes first responder and the keyboard appears.
You can check the status of the keyboard with [myTextField isFirstResponder]. If it returns YES, then the the keyboard is active.
The recommended pattern for a singleton object would be as follows. dispatch_once makes sure the class is initialised once in a thread-safe way, and the static variable isn't visible outside. And it's standard GCD, so no need to know about low level details of Objective-C.
Usually you don't want to know just whether the keyboard is visible or not, but how big it is. Keyboards don't all have the same size. iPhone keyboards are smaller than iPad keyboards. So you'd want another property @property (readonly, nonatomic) CGRect keyboardRect; which is set in the noticeShowKeyboard: method like this:
NSValue* value = notification.userInfo [UIKeyboardFrameEndUserInfoKey];
_keyboardRect = value.CGRectValue;
Important to notice that the rectangle is in UIWindow coordinates and doesn't respect screen rotation. So the caller would convert that rectangle by calling
If the user rotates the screen while the keyboard is visible, the app will be told that the keyboard is hidden, then shown again. When it is shown, other views are most likely not rotated yet. So if you observe keyboard hide/show events yourself, convert the coordinates when you actually need them, not in the notification.
If the user splits or undocks the keyboard, or uses a hardware keyboard, the notifications will always show the keyboard as hidden. Undocking or merging the keyboard will send a "keyboard shown" notification.
The listener must be initialised while the keyboard is hidden, otherwise the first notification will be missed, and it will be assumed that the keyboard is hidden when it's not.
So it is quite important to know what you actually want. This code is useful to move things out of the way of the keyboard (with a split or undocked keyboard, that's the responsibility of the user). It doesn't tell you whether the user can see a keyboard on the screen (in case of a split keyboard). It doesn't tell you whether the user can type (for example when there is a hardware keyboard). Looking at other windows doesn't work if the app creates other windows itself.
Basically call "registerForKeyBoardNotifications" in your ViewDidLoad. Then every time the keyboard becomes active, "keyboardWasShown" is called. And every time the keyboard disappears, "keyboardWillBeHidden" is called.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification {
NSLog(@"Keyboard is active.");
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification {
NSLog(@"Keyboard is hidden");
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
Using the window subview hierarchy as indication for keyboard showing is a hack. If Apple changers their underlying implementation all these answers would break.
The correct way would be to monitor Keyboard show and hide notifications application wide such as inside your App Delegate: