This is not a complete solution, but it should give you a good starting point.
Add the following ivars to your UIViewController:
CGRect keyboardSuperFrame; // frame of keyboard when initially displayed UIView * keyboardSuperView; // reference to keyboard view
Add inputAccessoryView to the text controller. I created a small view for insertion as an accessory:
accView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)]; accView.backgroundColor = [UIColor clearColor]; textField.inputAccessoryView = accView;
I added the code above -(void)loadView
Register to receive UIKeyboardDidShowNotification and UIKeyboardDidHideNotification when loading a view:
- (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; return; }
Add methods specified as selectors for notifications:
// method is called whenever the keyboard is about to be displayed - (void)keyboardWillShow:(NSNotification *)notification { // makes keyboard view visible incase it was hidden keyboardSuperView.hidden = NO; return; } // method is called whenever the keyboard is displayed - (void) keyboardDidShow:(NSNotification *)note { // save reference to keyboard so we can easily determine // if it is currently displayed keyboardSuperView = textField.inputAccessoryView.superview; // save current frame of keyboard so we can reference the original position later keyboardSuperFrame = textField.inputAccessoryView.superview.frame; return; }
Add methods to track the touch and update the look of the keyboard:
// stops tracking touches to divider - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { CGRect newFrame; CGRect bounds = [[UIScreen mainScreen] bounds]; newFrame = keyboardSuperFrame; newFrame.origin.y = bounds.size.height; if ((keyboardSuperView.superview)) if (keyboardSuperFrame.origin.y != keyboardSuperView.frame.origin.y) [UIView animateWithDuration:0.2 animations:^{keyboardSuperView.frame = newFrame;} completion:^(BOOL finished){ keyboardSuperView.hidden = YES; keyboardSuperView.frame = keyboardSuperFrame; [textField resignFirstResponder]; }]; return; } // updates divider view position based upon movement of touches - (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch * touch; CGPoint point; CGFloat updateY; if ((touch = [touches anyObject])) { point = [touch locationInView:self.view]; if ((keyboardSuperView.superview)) { updateY = keyboardSuperView.frame.origin.y; if (point.y < keyboardSuperFrame.origin.y) return; if ((point.y > updateY) || (point.y < updateY)) updateY = point.y; if (keyboardSuperView.frame.origin.y != updateY) keyboardSuperView.frame = CGRectMake(keyboardSuperFrame.origin.x, point.y, keyboardSuperFrame.size.width, keyboardSuperFrame.size.height); }; }; return; }
Denial of responsibility:
- When resigned, as they first answered, the keyboard will return to its original position before moving off the screen. To remove the keyboard with more fluid, you first need to create an animation to bring the keyboard off the screen, and then hide the view. I will leave this part as an exercise for readers.
- I tested it only on the iOS 5 simulator and iPhone with iOS 5. I did not test it with earlier versions of iOS.
The SlidingKeyboard project I created to test this concept is available on GitHub in the BindleKit sample directory:
https://github.com/bindle/BindleKit
Edit: An example update for the first disclaimer.