Отож, після годинних виснажливих робіт, намагаючись використовувати ці поточні рішення (і зовсім не вдається), я нарешті змусив роботу добре працювати, і оновив їх, щоб використовувати нові анімаційні блоки. Моя відповідь повністю ґрунтується на відповіді Ортвіна вище .
Тому з будь-якої причини код вище для мене просто не працює. Моя установка здавалася досить схожою на інші, але, можливо, тому, що я був на iPad або 4.3 ... поняття не маю. Це робило якусь дурну математику і знімав мою таблицю з екрану.
Дивіться кінцевий результат мого рішення: http://screencast.com/t/hjBCuRrPC (Будь ласка, ігноруйте фотографію. :-P)
Тож я пішов із суттю того, що робив Ортвін, але змінив, як він робив певну математику, щоб додати origin.y & size.height мого подання таблиці з висотою клавіатури. Коли я віднімаю висоту вікна від цього результату, воно вказує мені, скільки перехрестя у мене відбувається. Якщо його більше 0 (він також має деяке перекриття), я виконую анімацію висоти кадру.
Крім того, були деякі проблеми з перемальовуванням, які були вирішені 1) Чекаючи прокрутки до комірки, поки не буде виконана анімація, і 2) використання параметра UIViewAnimationOptionBeginFromCurrentState при захованні клавіатури.
Пару речей, які слід зазначити.
- _topmostRowBeforeKeyboardWasShown & _originalFrame - це змінні екземпляри, оголошені у заголовку.
- self.guestEntryTableView - це мій tableView (я перебуваю у зовнішньому файлі)
- IASKCGRectSwap - метод Ортвіна для гортання координат кадру
- Я оновлюю висоту tableView лише в тому випадку, якщо буде показано щонайменше 50 пікселів
- Оскільки я не перебуваю у UIViewController, я не маю self.view, тому я просто повертаю tableView до його початкового кадру
Знову ж, я б не дійшов до цієї відповіді, якби я Ортвін не наголосив на цьому суть. Ось код:
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
self.activeTextField = textField;
if ([self.guestEntryTableView indexPathsForVisibleRows].count) {
_topmostRowBeforeKeyboardWasShown = (NSIndexPath*)[[self.guestEntryTableView indexPathsForVisibleRows] objectAtIndex:0];
} else {
// this should never happen
_topmostRowBeforeKeyboardWasShown = [NSIndexPath indexPathForRow:0 inSection:0];
[textField resignFirstResponder];
}
}
- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
self.activeTextField = nil;
}
- (void)keyboardWillShow:(NSNotification*)notification {
NSDictionary* userInfo = [notification userInfo];
NSValue* keyboardFrameValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
// Reduce the tableView height by the part of the keyboard that actually covers the tableView
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
CGRect viewRectAbsolute = [self.guestEntryTableView convertRect:self.guestEntryTableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
if (UIInterfaceOrientationLandscapeLeft == orientation ||UIInterfaceOrientationLandscapeRight == orientation ) {
windowRect = IASKCGRectSwap(windowRect);
viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);
keyboardFrame = IASKCGRectSwap(keyboardFrame);
}
// fix the coordinates of our rect to have a top left origin 0,0
viewRectAbsolute = FixOriginRotation(viewRectAbsolute, orientation, windowRect.size.width, windowRect.size.height);
CGRect frame = self.guestEntryTableView.frame;
_originalFrame = self.guestEntryTableView.frame;
int remainder = (viewRectAbsolute.origin.y + viewRectAbsolute.size.height + keyboardFrame.size.height) - windowRect.size.height;
if (remainder > 0 && !(remainder > frame.size.height + 50)) {
frame.size.height = frame.size.height - remainder;
float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration: duration
animations:^{
self.guestEntryTableView.frame = frame;
}
completion:^(BOOL finished){
UITableViewCell *textFieldCell = (UITableViewCell*) [[self.activeTextField superview] superview];
NSIndexPath *textFieldIndexPath = [self.guestEntryTableView indexPathForCell:textFieldCell];
[self.guestEntryTableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}];
}
}
- (void)keyboardWillHide:(NSNotification*)notification {
NSDictionary* userInfo = [notification userInfo];
float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration: duration
delay: 0.0
options: (UIViewAnimationOptionBeginFromCurrentState)
animations:^{
self.guestEntryTableView.frame = _originalFrame;
}
completion:^(BOOL finished){
[self.guestEntryTableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
}];
}
#pragma mark CGRect Utility function
CGRect IASKCGRectSwap(CGRect rect) {
CGRect newRect;
newRect.origin.x = rect.origin.y;
newRect.origin.y = rect.origin.x;
newRect.size.width = rect.size.height;
newRect.size.height = rect.size.width;
return newRect;
}
CGRect FixOriginRotation(CGRect rect, UIInterfaceOrientation orientation, int parentWidth, int parentHeight) {
CGRect newRect;
switch(orientation)
{
case UIInterfaceOrientationLandscapeLeft:
newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), rect.origin.y, rect.size.width, rect.size.height);
break;
case UIInterfaceOrientationLandscapeRight:
newRect = CGRectMake(rect.origin.x, parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
break;
case UIInterfaceOrientationPortrait:
newRect = rect;
break;
case UIInterfaceOrientationPortraitUpsideDown:
newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
break;
}
return newRect;
}