Так что после нескольких часов изнурительной работы, пытаясь использовать эти текущие решения (и совершенно безуспешно), я наконец-то все заработало, и обновил их, чтобы использовать новые блоки анимации. Мой ответ полностью основан на ответе Ортвина выше .
Так что по какой-то причине приведенный выше код просто не работал для меня. Мои настройки казались довольно похожими на других, но, может быть, потому что я был на 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;
}