TableView frame not resizing properly when pushing a new view controller and the keyboard is hiding
I must be missing something fundamental here. I have a UITableView inside of a NavigationViewController. When a table row is selected in the UITableView (using tableView:didSelectRowAtIndexPath:) I call pushViewController to display a different view controller. The new view controller appears correctly, but when I pop that view controller and return the UITableView is resized as if the keyboard was being displayed. I need to find a way to have the keyboard hide before I push the view controller so that the frame is restored correctly. If I comment out the code to push the view controller then the keyboard hides correctly and the frame resizes correctly.
The code I use to show the keyboard is as follows:
- (void) keyboardDidShowNotification:(NSNotification *)inNotification {
NSLog(@"Keyboard Show");
if (keyboardVisible) return;
// We now resize the view accordingly to accomodate the keyboard being visible
keyboardVisible = YES;
CGRect bounds = [[[inNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
bounds = [self.view convertRect:bounds fromView:nil];
CGRect tableFrame = tableViewNewEntry.frame;
tableFrame.size.height -= bounds.size.height; // subtract the keyboard height
if (self.tabBarController != nil) {
tableFrame.size.height += 48; // add the tab bar height
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(shrinkDidEnd:finished:contextInfo:)];
tableViewNewEntry.frame = tableFrame;
[UIView commitAnimations];
}
The keyboard is hidden using:
- (void) keyboardWillHideNotification:(NSNotification *)inNotification {
if (!keyboardVisible) return;
NSLog(@"Keyboard Hide");
keyboardVisible = FALSE;
CGRect bounds = [[[inNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
bounds = [self.view c开发者_开发技巧onvertRect:bounds fromView:nil];
CGRect tableFrame = tableViewNewEntry.frame;
tableFrame.size.height += bounds.size.height; // add the keyboard height
if (self.tabBarController != nil) {
tableFrame.size.height -= 48; // subtract the tab bar height
}
tableViewNewEntry.frame = tableFrame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(_shrinkDidEnd:finished:contextInfo:)];
tableViewNewEntry.frame = tableFrame;
[UIView commitAnimations];
[tableViewNewEntry scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionMiddle animated:YES];
NSLog(@"Keyboard Hide Finished");
}
I trigger the keyboard being hidden by resigning first responser for any control that is the first responder in ViewWillDisappear. I have added NSLog statements and see things happening in the log file as follows:
Show Keyboard
ViewWillDisappear: Hiding Keyboard Hide Keyboard Keyboard Hide Finished PushViewController (an NSLog entry at the point I push the new view controller)From this trace, I can see things happening in the right order, but It seems like when the view controller is pushed that the keyboard hide code does not execute properly.
Any ideas would be really appreciated. I have been banging my head against the keyboard for a while trying to find out what I am doing wrong.
-- Added didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case 0: // Required Info
// removed to simplify
case 1: // Optional Info
switch (indexPath.row) {
case 0:
[self showTextDetailPicker: @"Enter a description"
tag: tDescriptionPicker
sourceTarget: self.newRecord
fieldSource: @selector(description)];
break;
default:
break;
}
break;
default:
break;
}
}
- (void) showTextDetailPicker: (NSString*) titleText tag:(int)tagID sourceTarget:(NSObject*)target fieldSource:(SEL)selector{
FieldEditorViewController *fe = [[FieldEditorViewController alloc] init];
fe.titleText = titleText;
fe.fieldText = [target performSelector: selector];
fe.tag = tagID;
// Replace default back button with one that just says 'Back'
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc]
initWithTitle:@"Back"
style:UIButtonTypeInfoLight
target:nil action:nil];
[[self navigationItem] setBackBarButtonItem: newBackButton];
[newBackButton release];
[fe setDelegate: self];
[self.navigationController pushViewController:fe animated:YES];
[fe release];
}
Right before you push your view controller, find the first responder and call resign. Use the category from this SO post to see how to find the first responder recursively (not sure if you're already doing this).
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIView *fp = [[self view] findFirstResponder];
[fp resignFirstResponder];
// Push new view controller here.
NextViewController *controller = [[NextViewController alloc] init];
[[self navigationController] pushViewController:controller animated:YES];
[controller release], controller = nil;
}
The other thing to keep in mind is that your table view is getting resized automatically because your root view controller is derived from UITableViewController (or so it seems). If you make your root view controller a regular UIViewController that contains a UITableView, you can manipulate the frame of the table view manually more easily--at least that's been my experience.
精彩评论