Pages

Wednesday, May 20, 2009

Moving the keyboard out of the way

After happily doing a little work for iphone, being content for that I was finished with it, I made realize that the text boxes near the bottom of the screen disappeared when the keyboard appeared after saying "hmmmm...", I started searching for a solution. Apples iphone developer library suggest this solution and here I am going to write about how I used it in my project. 
Here is how the problem looks like  in a simple case(a before),
What we are going to do is, we are going to define UIScrollView and put our view inside it and scroll it up when the keyboard shows up. In order to do it in a OO fashion I defined a base class that will handle the scroll details.
#import <UIKit/UIKit.h>

@interface BaseViewController : UIViewController <UITextFieldDelegate> {
bool keyboardShown;

UITextField * activeField;

UIScrollView * scrollView;

UIView * mainView;
}

@property (nonatomic, retain) IBOutlet UIScrollView * scrollView;
@property (nonatomic, retain) IBOutlet UIView * mainView;

@end
I will bind the mainView with the original view which contains the text field. The scrollView will be inside a proxy view. The implementation;
#import "BaseViewController.h"

@implementation BaseViewController

@synthesize mainView, scrollView;

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
return [theTextField resignFirstResponder];
}


- (void)textFieldDidBeginEditing:(UITextField *)textField {
activeField = textField;
}

- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification object:nil];
}

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
if (keyboardShown)
return;

NSDictionary* info = [aNotification userInfo];

// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;

// Resize the scroll view (which is the root view of the window)
CGRect viewFrame = [scrollView frame];
viewFrame.size.height -= keyboardSize.height;
scrollView.frame = viewFrame;

// Scroll the active text field into view.
CGRect textFieldRect = [activeField frame];
[scrollView scrollRectToVisible:textFieldRect animated:YES];
keyboardShown = YES;

}


// Called when the UIKeyboardDidHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];

// Get the size of the keyboard.
NSValue* aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;

// Reset the height of the scroll view to its original value
CGRect viewFrame = [scrollView frame];
viewFrame.size.height += keyboardSize.height;
scrollView.frame = viewFrame;
[scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
keyboardShown = NO;
}

- (void)viewDidLoad {
[super viewDidLoad];
keyboardShown = false;
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES; // default is NO, we want to restrict drawing within our scrollview
scrollView.scrollEnabled = NO;
scrollView.pagingEnabled = NO;
[scrollView setContentSize:CGSizeMake(320, 480)];
[scrollView addSubview:mainView];
[self registerForKeyboardNotifications];
}

@end
The example is here under KeyboardLift. And this is the after screenshot;

2 comments:

  1. Hello!

    I integrate your source code into my project. Your example KeyboardLift works great, buy my project doesn't work.
    What exactly should I do in Interface Builder?

    Thanks & Regards Tim

    ReplyDelete
  2. Thank you very much, this works fine

    In the IB you must delegate the textField to the BaseViewController because in the definition there is

    ReplyDelete