Sometimes form content needs to fill the entire iOS screen. So what do you do when the keyboard covers your UITextField or UITextView? In this quick tip I will demonstrate how to use a UIScrollView to keep your form content from being hidden when the keyboard slides into view.
According to the official Apple documentation, the best way to control a vertically stacked list of UITextField
objects that may be obscured by a keyboard is to embed them within a UIScrollView
object. When the keyboard is displayed, a UIKeyboardDidShowNotification
is sent and can be used to adjust the displayed text fields. When trapping this message, you need to take the following three steps:
- Determine the keyboard size.
- Update the bottom content inset of the content scroll view by the height of the keyboard.
- Scroll the target content into view.
Register Keyboard Observers
First, we need to register two observers for the keyboard notifications. One for the UIKeyboardDidShowNotification
and one for the UIKeyboardWillHideNotification
. We do this in the viewDidLoad:
method, so the observers will be registered when the view is loaded. You can add the observers with the following code:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
If you register an observer in the viewDidLoad:
method, you should also remove it in the viewDidUnload:
and the dealloc:
methods. So add the following code to both these methods:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Add the KeyboardWasShown method
The keyboardWasShown:
method will respond to the UIKeyboardDidShowNotification:
notification. In this method, we will implement the three steps recommended by Apple to move the content. Add the following code to your project:
- (void)keyboardWasShown:(NSNotification *)notification { // Step 1: Get the size of the keyboard. CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; // Step 2: Adjust the bottom content inset of your scroll view by the keyboard height. UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0); theScrollView.contentInset = contentInsets; theScrollView.scrollIndicatorInsets = contentInsets; // Step 3: Scroll the target text field into view. CGRect aRect = self.view.frame; aRect.size.height -= keyboardSize.height; if (!CGRectContainsPoint(aRect, activeTextField.frame.origin) ) { CGPoint scrollPoint = CGPointMake(0.0, activeTextField.frame.origin.y - (keyboardSize.height-15)); [theScrollView setContentOffset:scrollPoint animated:YES]; } }
In the first step we get the size of the keyboard. In the second step we adjust the bottom content inset of the scroll view by the keyboard height. In the third and last step we first create a new rect with the height of the screen minus the height of the keyboard. Then we check if the active text field is under the keyboard. If it isn’t under the keyboard, the scrollview won’t update the content offset. If the active text field is under the keyboard we update the scroll view’s content offset. I used (keyboardSize.height-15), so the active text field won’t be right above the textfield but will have an additional 15 pixels of spacing between it. activeTextField is a custom variable that stores the active field.
Add the KeyboardWillHide method
We also need to add the keyboardWillHide:
method, which will respond to the UIKeyboardWillHideNotification
. Add the following code to your project:
- (void) keyboardWillHide:(NSNotification *)notification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; theScrollView.contentInset = contentInsets; theScrollView.scrollIndicatorInsets = contentInsets; }
Here we set the contentInset
and the scrollIndicatorInsets
of the scroll view to UIEdgeInsetsZero
, so there won’t be a content inset anymore.
Tracking the Active UITextField
With these methods we track the active text field:
- (void)textFieldDidBeginEditing:(UITextField *)textField { self.activeTextField = textField; } - (void)textFieldDidEndEditing:(UITextField *)textField { self.activeTextField = nil; }
When we begin with the editing the activeTextField:
variable is set to the active field. When we end editing, the activeTextField:
variable is set to nil. Note that we declared the activeTextField
property with (nonatomic, assign)
, so the retain count is never incremented for the active text field by our assignment.
Dismiss the Keyboard
Add this code to dismiss the keyboard:
- (IBAction)dismissKeyboard:(id)sender { [activeTextField resignFirstResponder]; }
This action had didEndOnExit
as the event type, so if you press the return key, the keyboard will dismiss. You need to connect this action to every text field. Also connect the delegate from every textfield to File’s Owner.
Wrap Up
Thanks for reading this quick tip about moving content from under the Keyboard! If you have questions or comments on this tutorial, leave them in the comments section below!
Comments