Having not visited this topic in quite some time here is a brief update...
This code is working in my demo to this point. I setup a Messages type app for educational purposes. Table datasource and delegates not provided. Obviously the messages array isn't provided either.
Notes based on comments:
1.) You have to make sure you don't keep stacking controls on top of the keyboard. As you can see in keyboardDidHide method that I remove the text field from the keyboard and apply it back to the bottom of the tableview. And vice versa when when the keyboard is called again.
2.) Obviously this is not all the code but enough to make it work. Types are implied by what is being instantiated. If there is no type defined obviously it's defined in the header.
3.) IMPORTANT! Have not checked the code for memory leaks. Use at your own discretion.
Code:
@synthesize tableView;
@synthesize textField;
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.backgroundColor = [UIColor colorWithRed:(0xDD/255.0) green:(0xE2/255.0) blue:(0xEB/255.0) alpha:1.0];
self.view.backgroundColor = [UIColor colorWithRed:(0xDD/255.0) green:(0xE2/255.0) blue:(0xEB/255.0) alpha:1.0];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:self.view.window];
}
const int TEXTFIELD_HEIGHT = 30;
- (void) viewWillAppear:(BOOL)animated {
if(self.textField == nil) {
self.textField = [[KeyboardTextField alloc] initWithFrame:CGRectZero];
self.textField.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"border.png"]];
self.textField.delegate = self;
self.textField.returnKeyType = UIReturnKeySend;
[self.view addSubview:self.textField];
self.textField.frame = CGRectMake(0, self.view.frame.size.height - TEXTFIELD_HEIGHT, self.view.frame.size.width, TEXTFIELD_HEIGHT);
}
NSString *dummyData = [[NSBundle mainBundle] pathForResource:@"dummy" ofType:@"plist"];
messages = [[NSArray arrayWithContentsOfFile:dummyData] retain];
if(messages.count > 0) {
NSDictionary* dictionary = [messages objectAtIndex:0];
self.title = [dictionary objectForKey:@"sender"];
}
[self.tableView reloadData]; // manually sync datasource so we can scroll to the bottom
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self scrollToBottom];
}
- (void)keyboardWillShow:(NSNotification *)notification {
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
// Now iterating over each subview of the available windows
for (UIView *keyboard in [keyboardWindow subviews]) {
// Check to see if the description of the view we have referenced is UIKeyboard.
// If so then we found the keyboard view that we were looking for.
if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES) {
NSValue *v = [[notification userInfo] valueForKey:UIKeyboardBoundsUserInfoKey];
CGRect kbBounds = [v CGRectValue];
keyboard.bounds = CGRectMake(kbBounds.origin.x, kbBounds.origin.y, kbBounds.size.width, kbBounds.size.height + (TEXTFIELD_HEIGHT * 2));
textField.frame = CGRectMake(0, 0, kbBounds.size.width, TEXTFIELD_HEIGHT);
[textField removeFromSuperview];
[keyboard addSubview:textField];
for(UIView* subKeyboard in [keyboard subviews]) {
if([[subKeyboard description] hasPrefix:@"<UIKeyboardImpl"] == YES) {
keyboardBounds = CGRectMake(kbBounds.origin.x, kbBounds.origin.y - TEXTFIELD_HEIGHT, kbBounds.size.width, kbBounds.size.height);
subKeyboard.bounds = keyboardBounds;
}
}
}
}
}
}
- (void)keyboardDidShow:(NSNotification*)notification {
self.tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - keyboardBounds.size.height - TEXTFIELD_HEIGHT);
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:messages.count - 1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
- (void)keyboardWillHide:(NSNotification*)notification {
textField.text = nil;
}
- (void)keyboardDidHide:(NSNotification*)notification {
[textField removeFromSuperview];
textField.text = nil;
[self.view addSubview:textField];
textField.frame = CGRectMake(0, self.view.frame.size.height - TEXTFIELD_HEIGHT, textField.frame.size.width, textField.frame.size.height);
self.tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - TEXTFIELD_HEIGHT);
[self scrollToBottom];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self.textField resignFirstResponder];
return NO;
}
- (void) scrollToBottom {
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:messages.count - 1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}