Adjust TextField Hidden by Keyboard

Mon, Nov 2

Welcome to the first in a series of tips that are based on content from one of O’Reilly’s latest iPhone books, Head First iPhone Development, written by Dan and Tracey Pilone. Each Monday in November I’ll write a tip that is based on ideas and code in the book.

Book Giveaway – Every Friday in November

O’Reilly and iPhone Developer Tips are collaborating to give away a free ebook (electronic copy) of Head First iPhone Development each Friday in November. You can register in this weeks drawing by referring a friend to this tip – see the Refer-a-Friend button near the bottom of this post.

UITextField Hidden by Keyboard

Have you ever had one or more textfields on screen, that when tapped, become hidden by the on-screen keyboard? This tip will show an example of how to adjust textfields that are contained within a scrollview such that they are always visible, even when entering text.

The inspiration for this tip comes from Chapter 6, Saving, Editing and Sorting Data. The code example in the book is created over a series of chapters – to provide a complete working example for this tip, I’ll write a small working example from the ground up that you can download and build using Xcode. I’ll write all the code for the UI without Interface Builder, which will provide a little more insight into how all the pieces fit together.

The UI Problem

Let’s get started – When working with UITextFields, depending on the layout of your screen, good chance the keyboard will overlay your textfield when a user taps on the field to start editing. For example, the screenshot below shows two textfields, both displayed within a scrollview.

When the user selects either textfield, the keyboard will appear, trouble is, the keyboard may overlay the textfields as shown here:

Scrollview with Two UITextFields

For this code example, I’ll wrap two UITextFields inside a scrollview. When the keyboard is shown, the scrollview size is adjust based on the size of the keyboard, allowing the textfield selected to be visible on the display.

Let’s look at the view controller that will contain the textfields and the scrollview:

@interface test_appViewController : UIViewController  <UIScrollViewDelegate, UITextFieldDelegate>
{
  BOOL           keyboardVisible;
  CGPoint        offset;
  UIScrollView  *scrollview;
  UITextField    *textfield;
  UITextField    *textfield2;
}

The variable keyboardVisible will keep the state of whether or not the keyboard is visible. The variable offset will keep track of current offset of the scrollview, before the keyboard is shown, so when the keyboard is dismissed, we can return the scrollview to its original position.

UI Layout

The code that follows show the layout of the user interface, a view that contains a scrollview, which in turn, contains two textfields.

#define SCROLLVIEW_HEIGHT 460
#define SCROLLVIEW_WIDTH  320
 
#define SCROLLVIEW_CONTENT_HEIGHT 720
#define SCROLLVIEW_CONTENT_WIDTH  320
 
...
 
- (id)init
{
  if (self = [super init]) 
  {
    self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
    self.view.backgroundColor = [UIColor whiteColor];
 
    // Create scrollview
    scrollview = [[UIScrollView alloc] init];      
    scrollview.contentSize = CGSizeMake(SCROLLVIEW_CONTENT_WIDTH, SCROLLVIEW_CONTENT_HEIGHT);
    scrollview.frame = CGRectMake(0, 0, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
    scrollview.scrollsToTop = NO;
    scrollview.delegate = self;
    [self.view addSubview:scrollview];
 
    // Create textfield 1
    textfield = [[UITextField alloc] initWithFrame:CGRectMake(20, 240, 280, 30)];
    textfield.placeholder = @"Textfield 1";
    textfield.delegate = self;
    textfield.returnKeyType = UIReturnKeyDone;
    textfield.borderStyle = UITextBorderStyleBezel;
    textfield.enablesReturnKeyAutomatically = TRUE;
    [scrollview addSubview:textfield];  
 
    // Create textfield 2
    textfield2 = [[UITextField alloc] initWithFrame:CGRectMake(20, 290, 280, 30)];
    textfield2.placeholder = @"Textfield 2";
    textfield2.delegate = self;
    textfield2.returnKeyType = UIReturnKeyDone;
    textfield2.borderStyle = UITextBorderStyleBezel;
    textfield2.enablesReturnKeyAutomatically = TRUE;
    [scrollview addSubview:textfield2];  
  }
 
  return self;  
}
Keyboard Notifications

The magic behind all of this begins by registering to receive notifications when the keyboard is shown and when it is hidden. You can read more about notifications on this iPhone Developer Tip: Basics of Notifications.

To add the notifications for the keyboard, here’s all we need to do:

[[NSNotificationCenter defaultCenter] addObserver:self
   selector:@selector (keyboardDidShow:)
   name: UIKeyboardDidShowNotification object:nil];
 
[[NSNotificationCenter defaultCenter] addObserver:self 
   selector:@selector (keyboardDidHide:)
	name: UIKeyboardDidHideNotification object:nil];

These calls request that the methods keyboardDidShow and keyboardDidHide be called when the notifications UIKeyboardDidShowNotification and UIKeyboardDidHideNotification, respectively, are fired.

Keyboard Visible Code

The OS will trigger the notification UIKeyboardDidShowNotification when a user taps in a textfield, which will in turn call the method shown below. The first check is to see if the keyboard is currently visible, if so, we’re done. If not, access the dictionary for the notification so we can get to the keyboard size – this is important as the keyboard size can vary depending on the textfield.

With the keyboard size known, we can now adjust (shrink) the scrollview frame so the keyboard and scrollview share the screen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-(void) keyboardDidShow: (NSNotification *)notif 
{
  // If keyboard is visible, return
  if (keyboardVisible) 
  {
    NSLog(@"Keyboard is already visible. Ignoring notification.");
    return;
  }
 
  // Get the size of the keyboard.
  NSDictionary* info = [notif userInfo];
  NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
  CGSize keyboardSize = [aValue CGRectValue].size;
 
  // Save the current location so we can restore
  // when keyboard is dismissed
  offset = scrollview.contentOffset;
 
  // Resize the scroll view to make room for the keyboard
  CGRect viewFrame = scrollview.frame;
  viewFrame.size.height -= keyboardSize.height;
  scrollview.frame = viewFrame;
 
  // Keyboard is now visible
  keyboardVisible = YES;
}

One line of code to point is line 17, where we save the current offset of the scrollview so we can restore the position once the keyboard is hidden.

Keyboard Hidden Code

Upon dismissing the keyboard, the code below will be called. The basic idea is to reset the size of the scrollview to its original size, and follow this by updating the scrollview offset to where it was prior to the keyboard being shown.

-(void) keyboardDidHide: (NSNotification *)notif 
{
  // Is the keyboard already shown
  if (!keyboardVisible) 
  {
    NSLog(@"Keyboard is already hidden. Ignoring notification.");
    return;
  }
 
  // Reset the height of the scroll view to its original value
  scrollview.frame = CGRectMake(0, 0, SCROLLVIEW_WIDTH, SCROLLVIEW_HEIGHT);
 
  // Reset the scrollview to previous location
  scrollview.contentOffset = offset;
 
  // Keyboard is no longer visible
  keyboardVisible = NO;	
}
Final User Interface

The end result is shown below – when the keyboard is shown, the scrollview is adjusted to the textfields are visible.

Xcode Project Source Code

You can download the Xcode project with source code here.

Book Giveaway

The drawing for this weeks free eBook is now closed.

12 comments

Nice tip, easy to understand. Thanks for the Xcode project file, that helps a lot to see how all this works!

by low on Nov 2, 2009. #

Referred a friend! Hope I win the book! :D

by Koh Jing Yu on Nov 2, 2009. #

Awesome, I’ve been looking for a way around this :)

by PeterK on Nov 2, 2009. #

Oh wow, a whole copy of a PDF file each Friday? That sounds great!

by anon on Nov 2, 2009. #

Referred a friend. I could definately use an iPhone development book.

by Roman Sharma on Nov 2, 2009. #

Referred a friend too. I have tons of App ideas, but don’t know where to start. this book will definitely help.

by Yogesh on Nov 3, 2009. #

I’ve just improved a little bit your solution by using an active field which I set when the Field will begin to edit. Anyway, thanks! You writing was a great starting point to solve my problem.

If you wish check the “extended” tutorial here: http://www.iphonesampleapps.com/2009/12/adjust-uitextfield-hidden-behind-keyboard-with-uiscrollview/

by Jose Muanis on Dec 20, 2009. #

Hi,

Because I am just using 1 UITextField, to make a simple “word proccessor”, can this code also be applyed to my single UITextField?

Max.

by Max on Apr 1, 2010. #

A different approach, simpler and i think more correct is to move the view upwards, instead of adding a scroll view
take a look in the following link for an example:
http://stackoverflow.com/questions/1126726/how-to-make-a-uitextfield-move-up-when-keyboard-is-present

by Menachi on Sep 17, 2010. #

thanks Menachi…

thats pretty good..

by makboney on Dec 13, 2010. #

Thanks man!

by Dr. Strangecode on Dec 12, 2011. #

Thank you! It’s very useful.

by Youshunei on Dec 18, 2011. #