Подтвердить что ты не робот

UITableView прыгает вверх на endUpdates при вводе внутри ячейки на iOS 8 автовысоте

Я использую iOS 8 для самостоятельной калибровки (tableView.rowHeight = UITableViewAutomaticDimension и tableView:estimatedHeightForRowAtIndexPath:). Он отлично работает, пока я не набираю что-то внутри ячейки. Когда я набираю текст, я вызываю пару beginUpdates/endUpdates для изменения размера моей ячейки (текстовое представление растет по мере того, как я печатаю и сжимаю, когда я удаляю), но каждый вызов приводит к плохим переходам в начало представления таблицы. Если я удалю пару beginUpdates/endUpdates, то она не будет прыгать, но моя ячейка не изменит размер по мере ввода.

Вот демонстрация проблемы:

enter image description here

Как я могу заставить свою ячейку правильно изменять размер при вводе, не переходя в верхнюю часть представления таблицы? Я ориентируюсь только на iOS >= 8, поэтому мне не нужна какая-либо совместимость с iOS 7.

4b9b3361

Ответ 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 всегда равна высоте ячейки и никогда не прокручивается.