Прокрутка UITableView до верхней части обновления ячейки
У меня есть UITableView с ячейкой, которая имеет динамический размер, чтобы соответствовать UITextView внутри него. Всякий раз, когда вводится ключ, ячейка проверяет, увеличилась ли подсчитанная высота, как и в новой строке, поэтому она может сообщить таблице, что высота ячейки должна быть пересчитана. Я делаю это с помощью этого кода.
- (void) createNoteCellViewDidUpdate: (CreateNoteCell*) cell {
CGFloat newHeight = [self tableView:self.tableView heightForRowAtIndexPath:CreateNoteCellIndexPath];
if (newHeight != CGRectGetHeight(cell.contentView.frame)) {
[self.tableView beginUpdates];
[self.tableView endUpdates]; // <- HERE IS WHERE THE CONTENT OFFSET CHANGES
}
}
Границы изменения размера и таблицы соответствуют ожиданиям. Но вместо того, чтобы просто оживлять изменение высоты, он также прокручивается вверх. Это можно увидеть здесь, нажав клавишу возврата.
![table scrolling on cell resize]()
По наблюдению за ключевым значением, я обнаружил, что представление содержимого прокруткиOffset устанавливается при изменении вида содержимого прокрутки. И что contentSize меняет много раз, когда вызывается метод endUpdates. Когда он меняется, он идет от нормальной высоты, до довольно большой высоты, а затем возвращается к нормальной высоте. Интересно, будет ли это из-за этого. Я не знаю, куда идти отсюда.
Ответы
Ответ 1
Ничего себе, ответ Джоша Гафни очень помог; он заслуживает продолжения. Мое решение основано на его. Это по-прежнему кажется взломом, поэтому, если у кого-то еще есть лучший способ сделать это, мне все равно очень интересно это услышать.
Сначала я сохраняю смещение содержимого, затем запускаю обновление.
CGPoint offset = self.tableView.contentOffset;
[self.tableView beginUpdates];
[self.tableView endUpdates];
Это оживляет изменение высоты ячейки и настраивает все кадры в соответствии с ограничениями.
Затем я удаляю все анимации из слоя tableView, поэтому анимация на вершине останавливается. Тогда я reset contentOffst к тому, что было раньше.
[self.tableView.layer removeAllAnimations];
[self.tableView setContentOffset:offset animated:NO];
Наконец, я разрешаю tableView обрабатывать анимированную прокрутку вниз, так что нижняя часть ячейки находится прямо над клавиатурой.
[self.tableView scrollToRowAtIndexPath:CreateNoteCellIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
И вуаля, это работает очень хорошо.
![fixed cell resize]()
Ответ 2
Просто догадаться...
Сохраните contentOffset
uitableview перед любыми изменениями. Затем установите его снова.
CGFloat contentOffset = self.tableView.contentOffset;
а затем после изменений
self.tableView.contentOffset = contentOffset;
Ответ 3
Вот мое расширение UITableView, которое отлично работает. В Swift 2.1. На основании принятого ответа.
extension UITableView
{
func reloadDataAnimatedKeepingOffset()
{
let offset = contentOffset
UIView.setAnimationsEnabled(false)
beginUpdates()
endUpdates()
UIView.setAnimationsEnabled(true)
layoutIfNeeded()
contentOffset = offset
}
}
Ответ 4
Более упрощенное решение (добавьте наблюдателя уведомлений при изменении текста), Swift-версию. Основной трюк использует UIView.setAnimationsEnabled
.
func textViewDidChanged(notification: NSNotification) {
UIView.setAnimationsEnabled(false)
let contentOffset = self.tableView.contentOffset
tableView.beginUpdates()
tableView.endUpdates()
tableView.contentOffset = contentOffset
UIView.setAnimationsEnabled(true)
}