UITableView прыгает вверх на endUpdates при вводе внутри ячейки на iOS 8 автовысоте
Я использую iOS 8 для самостоятельной калибровки (tableView.rowHeight = UITableViewAutomaticDimension
и tableView:estimatedHeightForRowAtIndexPath:
). Он отлично работает, пока я не набираю что-то внутри ячейки. Когда я набираю текст, я вызываю пару beginUpdates
/endUpdates
для изменения размера моей ячейки (текстовое представление растет по мере того, как я печатаю и сжимаю, когда я удаляю), но каждый вызов приводит к плохим переходам в начало представления таблицы. Если я удалю пару beginUpdates
/endUpdates
, то она не будет прыгать, но моя ячейка не изменит размер по мере ввода.
Вот демонстрация проблемы:
![enter image description here]()
Как я могу заставить свою ячейку правильно изменять размер при вводе, не переходя в верхнюю часть представления таблицы? Я ориентируюсь только на iOS >= 8, поэтому мне не нужна какая-либо совместимость с iOS 7.
Ответы
Ответ 1
Я реализовал точно то же самое для чат-приложения и получал ту же проблему, что и сейчас. Это помогло мне. Сообщите мне, если это сработает и для вас.
UIView.setAnimationsEnabled(false)
tableView.beginUpdates()
cell.textView.scrollRangeToVisible(NSMakeRange(cell.textView.text.characters.count-1, 0))
tableView.endUpdates()
UIView.setAnimationsEnabled(true)
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false)
Ответ 2
У меня такая же проблема, и я смог свести к минимуму (но не исключать) переключение, только сделав уведомление об изменении размера/обновлении, когда фактический размер содержимого действительно изменился, например:
Swift
var textViewHeight: CGFloat = 0.0 // Set in viewWillAppear as below
...
func textViewDidChange(textView: UITextView) {
let newHeight = textView.intrinsicContentSize().height
if textViewHeight != newHeight{
textViewHeight = newHeight
tableView.beginUpdates()
tableView.endUpdates()
}
}
Objective-C
CGFloat textViewHeight = 0.0; // Set in viewWillAppear as below
...
(void)textViewDidChange:(UITextView *)textView {
CGFloat newHeight = [textView intrinsicContentSize].height;
if (textViewHeight != newHeight){
textViewHeight = newHeight
[tableView beginUpdates];
[tableView endUpdates];
}
}
Ответ 3
Является ли ваш ресетевый кадр таблицы со списком в тексте начинать редактирование? Если да, то иногда вы можете проверять свои переменные из-за того, что переменные распределения памяти освобождаются. Используйте точки останова и проверяйте значения переменных, которые не могут быть изменены согласно вашему требованию.
Ответ 4
Автомакет имеет некоторый недостаток, связанный с ним. Когда вы начинаете вводить его, прыгайте, потому что все остальные ячейки корректируют свой размер, поэтому будет лучше, если вы вычисляете размеры ячейки только во время выполнения.
Ответ 5
Я нашел решение от Manoj Aher, чтобы работать нормально - текст вообще не прыгает. Но в моем случае я должен был распространяться на ситуации, когда пользователь мог вводить гораздо больше текста (так что ячейка таблицы больше видимой части таблицы), а затем возвращается, чтобы редактировать этот текст где-то в начале или в середине. Поэтому мне пришлось прокручивать ячейку таблицы до вершины или середины в зависимости от того, где пользователь вводит текст, чтобы сохранить отображаемую позицию.
Сначала помните indexPath для ячейки любым удобным способом. Например:
var cellIndexChosenForEdition: NSIndexPath
...
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
cellIndexChosenForEdition = indexPath
...
}
In shouldChangeTextInRange или любой другой метод, который вызывается, когда пользовательские типы (показано здесь, метод будет вызываться, когда ваш контроллер просмотра соответствует протоколу UITextViewDelegate):
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
...
UIView.setAnimationsEnabled(false)
MyTableView.beginUpdates()
MyTableView.endUpdates()
UIView.setAnimationsEnabled(true)
if let textStartPosition: UITextPosition = textView.selectedTextRange?.start {
let cursorPosition = textView.offsetFromPosition(textView.beginningOfDocument, toPosition: textStartPosition)
if textView.text.characters.count - cursorPosition < 170 {
table_create_issue.scrollToRowAtIndexPath(cellIndexChosenForEdition, atScrollPosition: .Bottom, animated: false)
} else if cursorPosition > 200 {
table_create_issue.scrollToRowAtIndexPath(cellIndexChosenForEdition, atScrollPosition: .Middle, animated: false)
} else {
table_create_issue.scrollToRowAtIndexPath(cellIndexChosenForEdition, atScrollPosition: .Top, animated: false)
}
}
...
}
* константы 200 и 170 должны быть изменены в соответствии с конкретной ситуацией.
** Я не использовал scrollRangeToVisible, потому что моя высота textView всегда равна высоте ячейки и никогда не прокручивается.