Move view when keyboard appears

When a user needs to input some text, the keyboard will show. One of the big problems is, the keyboard is blocking the view which needs input so it isn't visible while entering text. In this tutorial, i will show you how to move the view back in place, using a scrollview.

Update: Feb 2, 2015. The rewritten version in Swift for iOS 8.1 and Xcode 6.1 is available here.

Open Xcode and create a new Single View Application. For product name, use KeyboardDemo and then fill out the Organization Name, Company Identifier and Class Prefix fields with your customary values. Make sure only iPhone is selected in Devices, and that the Use Storyboards is deselected and Use Automatic Reference Counting checkbox is selected.

First, let's create the user interface. Go to ViewController.xib and drag a Navigation Bar to the top of the view. Double-click on the title and change it to KeyBoardDemo. Drag a Bar Button Item to the right of the Navigation Bar. Select the Bar Button Item and go to the Attributes Inspector. Change the Identifier in "Done". Drag a Scroll View to the view and resize it in the remaining space below the Navigation Bar. Drag a Text View to the view and give it the same size the Scroll View has. In the outline View, drag the Text View on to the Scroll View so it will become a subview of it. The view should look like this.

Build and Run, click inside the Text View and enter some text. When the cursor drops behind the keyboard, it isn't visible what the user is entering anymore. Let's fix it by scrolling the Text View while entering text.

First, in ViewController.m add the following properties and IBAction method in the interface section.

@interface ViewController ()

@property (nonatomic, strong) IBOutlet UITextView* textView;
@property (nonatomic, strong) IBOutlet UIScrollView *scrollView;

- (IBAction)dismissKeyboard:(id)sender;


Go back to ViewController.xib and make the following connections.

  • Text View -> textView IBOutlet
  • Scroll View -> scrollView IBOutlet
  • Done Bar Button Item -> dismissKeyboard IBAction

Let's change the background to white. Change the viewDidLoad method in ViewController.m to

- (void)viewDidLoad 
[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

Notifications are an way to send messages between objects. iOS broadcasts various notifications related to the keyboard on the screen. In this tutorial we'll use UIKeyboardWillShowNotification and UIKeyboardWillHideNotification .To listen for notifications, an object must add itself as an observer. Add the viewDidAppear method

- (void)viewWillAppear:(BOOL)animated 
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

When the notifications occur the corresponding selectors will be called. When the view isn't visible anymore we can remove the observer. Add the viewWillDisappear method

- (void)viewWillDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter] removeObserver:self]; 

Implement the keyboardWillShow method

- (void)keyboardWillShow:(NSNotification*)notification 
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);

self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;

CGRect rect = self.view.frame; rect.size.height -= keyboardSize.height;

if (!CGRectContainsPoint(rect, self.textView.frame.origin))
CGPoint scrollPoint = CGPointMake(0.0, self.textView.frame.origin.y - (keyboardSize.height - self.textView.frame.size.height));
[self.scrollView setContentOffset:scrollPoint animated:NO];

When the object receives the notification, additional info is send along in the form of a user information dictionary. We extract the keyboardsize from this dictionary. The contentInsets defines a bottom inset for the scrollView. we define a rect object of our current view minus the keyboard height. In the if statement the scrollView is set to a new Content Offset so it is moving up in the view above the keyboard. Implement the keyboardWillHide method.

- (void)keyboardWillHide:(NSNotification *)notification 
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;

All Content inset from the scroll View are reset to 0. Build and Run, you should see the view scroll up when the cursor is behind the keyboard. There's still one problem, as we have set the keyboard to default, the enter key behaves as a normal enter key. Currentrly we can't dismiss the keyboard. We need to set our ViewController as a textview delegate to dismiss the keyboard when finished. Change the @interface line to

@interface ViewController () <UITextViewDelegate>

Add the following line to the end of viewDidLoad

self.textView.delegate = self;

Now add the following Text View delegate method

- (BOOL)textViewShouldEndEditing:(UITextView *)textView 
[textView resignFirstResponder];
return YES;

The first responder status is given back to the main view. Finally, implement the keyboardWillHide method

- (IBAction)dismissKeyboard:(id)sender 
[self textViewShouldEndEditing:self.textView];

This method simply calls the textViewShouldEndEnding method.Build and run, when you press the "Done" button the keyboard will be dismissed.

You can download the source code of the KeyboardDemo at the ioscreator repository on github.